http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3128
题意:给你n条直线(n<=10000),求(l,r)区间内的交点个数
解法:每条直线分别与x=l 和 x=r求交点,这样就转换成了 n条线段 两端点在x=l 和x =r上,求有几个交点,这样就转换成了求逆序数的问题了
#include<cstdio> #include<cstring> #include<cmath> #include<iostream> #include<algorithm> using namespace std; const double eps = 1e-8; const int maxn = 10010; int c[maxn],ans; void update(int x,int d){ for(;x>0;x-=x&-x) c[x]+=d; } int sum(int x){ for(ans=0;x<maxn;x+=x&-x) ans+=c[x]; return ans; } struct point { double x,y; }; struct L{ point a,b; double h1,h2; int id; }in[maxn]; int tmp[maxn]; int cmp(L x,L y){ if(fabs(x.h1-y.h1)<eps) return x.h2<y.h2; return x.h1<y.h1; } int cmp2(L x,L y){ if(fabs(x.h2-y.h2)<eps) return x.h1<y.h1; return x.h2<y.h2; } int main(){ int n; double l,r; while(scanf("%d",&n)!=EOF){ for(int i=1;i<=n;i++) scanf("%lf%lf%lf%lf",&in[i].a.x,&in[i].a.y,&in[i].b.x,&in[i].b.y); scanf("%lf%lf",&l,&r); for(int i=1;i<=n;i++){ double k=(in[i].b.y-in[i].a.y)/(in[i].b.x-in[i].a.x); in[i].h1=k*(l-in[i].a.x)+in[i].a.y; in[i].h2=k*(r-in[i].a.x)+in[i].a.y; } sort(in+1,in+n+1,cmp); for(int i=1;i<=n;i++) in[i].id=i; sort(in+1,in+n+1,cmp2); for(int i=1;i<=n;i++) tmp[in[i].id]=i; memset(c,0,sizeof(c)); int s=0; for(int i=1;i<=n;i++){ s+=sum(tmp[i]+1); update(tmp[i],1); } printf("%d\n",s); } return 0; }