题意:给一些直线,问这些直线在直线x=L,x=R之间有多少个交点。
讲解见此文:http://blog.sina.com.cn/s/blog_778e7c6e0100q64a.html
首先将直线分别跟x=L+eps,x=R-eps(防止出现相同纵坐标,故+-eps)求他们的交点,求的纵坐标为low,high,首先按low从大到小排序,一次赋予一个ind值,再按high从大到小排序,此时ind的逆序对数即为(L,R)内的交点个数。成功将计算几何问题向树状数组转化。求逆序对数可用归并排序或者树状数组解决。
代码:(树状数组)
#include <iostream>
#include <cmath>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#define eps 1e-5
using namespace std;
#define N 10007 struct node
{
double x,y;
}; struct Line
{
node a,b;
int ind;
double low,high;
}line[N]; int c[N],n; int cmp(Line ka,Line kb)
{
return ka.low > kb.low;
} int cmp2(Line ka,Line kb)
{
return ka.high > kb.high;
} int lowbit(int x){ return x & (-x); } void modify(int x)
{
while(x <= n)
c[x]++,x += lowbit(x);
} int getsum(int x)
{
int res = ;
while(x > )
res += c[x],x -= lowbit(x);
return res;
} int main()
{
int i,x,j;
double L,R;
while(scanf("%d",&n)!=EOF)
{
memset(c,,sizeof(c));
for(i=;i<=n;i++)
scanf("%lf%lf%lf%lf",&line[i].a.x,&line[i].a.y,&line[i].b.x,&line[i].b.y);
scanf("%lf%lf",&L,&R);
L += eps,R -= eps;
for(i=;i<=n;i++)
{
double k = (line[i].b.y-line[i].a.y)/(line[i].b.x-line[i].a.x);
line[i].low = k*(L-line[i].a.x) + line[i].a.y;
line[i].high = k*(R-line[i].a.x) + line[i].a.y;
}
sort(line+,line+n+,cmp);
for(i=;i<=n;i++)
line[i].ind = i;
sort(line+,line+n+,cmp2);
int ans = ;
for(i=;i<=n;i++)
{
modify(line[i].ind);
ans += i - getsum(line[i].ind);
}
printf("%d\n",ans);
}
return ;
}