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;
}

posted @ 2011-04-07 20:18  金海峰  阅读(261)  评论(0编辑  收藏  举报