hoj3465

和计算几何相关的求逆序数,我是用树状数组做的,也可以用归并排序。 注意,由于是开区间所以读入区间后要将区间向内收缩eps.这道题还比较考察浮点数的相关知识。浮点数比较a<b要写成a+eps < b.

View Code
   
     
#include < iostream >
#include
< cstdio >
#include
< cstdlib >
#include
< cstring >
#include
< cmath >
#include
< algorithm >
using namespace std;

#define maxn 50005
#define eps 1.0e-8

struct Highway
{
double a, b;
} way[maxn];

int n, c[maxn], tot, add, totls;
double ls[maxn * 2 ], l, r;
long long ans;

void input()
{
scanf(
" %lf%lf " , & l, & r);
l
+= eps;
r
-= eps;
tot
= 0 ;
add
= 0 ;
totls
= 0 ;
for ( int i = 0 ; i < n; i ++ )
{
double x1, x2, y1, y2;
scanf(
" %lf%lf%lf%lf " , & x1, & y1, & x2, & y2);
if (abs(x1 - x2) > eps)
{
way[tot].a
= y2 - (y2 - y1) / (x2 - x1) * (x2 - l);
way[tot].b
= y2 + (y2 - y1) / (x2 - x1) * (r - x2);
ls[totls
++ ] = way[tot].b;
tot
++ ;
}
else if (x1 + eps < r && l + eps < x1)
add
++ ;
}
}

int binarysearch( double a)
{
int l = 0 , r = totls - 1 ;
int mid;
while (l < r)
{
mid
= (l + r) / 2 ;
if (ls[mid] + eps < a)
l
= mid + 1 ;
else
r
= mid;
}
return l;
}

bool cmp( const Highway & a, const Highway & b)
{
if (abs(a.a - b.a) > eps)
return a.a + eps < b.a;
return a.b + eps < b.b;
}

long long cal( int a)
{
long long sum = 0 ;
while (a > 0 )
{
sum
+= c[a];
a
-= (a & - a);
}
return sum;
}

void modify( int a, int x)
{
while (a <= tot)
{
c[a]
+= x;
a
+= (a & - a);
}
}

void work()
{
ans
= 0 ;
for ( int i = 0 ; i < tot; i ++ )
{
int temp = binarysearch(way[i].b) + 1 ;
ans
+= i - cal(temp);
modify(temp,
1 );
}
}

int main()
{
// freopen("D:\\t.txt", "r", stdin);
while (scanf( " %d " , & n) != EOF)
{
memset(c,
0 , sizeof (c));
input();
sort(way, way
+ tot, cmp);
sort(ls, ls
+ totls);
work();
printf(
" %I64d\n " , ans + tot * add);
}
return 0 ;
}

你可能感兴趣的:(OJ)