题目链接:hdu_5862_Counting Intersections
题意:
给你与坐标轴平行的线段,问你交点数
题解:
实质就是扫描线,这里我用树状数组来记录,所有线段按X坐标排序,遇到横线段的左端点就对应y坐标+1,遇到右端点,就对应y坐标-1,遇到竖线段,就询问对应的区间段
1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;++i) 3 using namespace std; 4 typedef long long ll; 5 6 const int N=1e5+7; 7 int sum[N*4],n,t,nn,has[N*4],cnt,x1,x2,y1,y2,ed,hed; 8 9 struct seg{ 10 int x,l,r,op; 11 bool operator<(const seg &b)const{return x<b.x||(x==b.x&&op<b.op);} 12 }s[N*2]; 13 14 inline void add(int x,int c){while(x<=n)sum[x]+=c,x+=x&-x;} 15 inline int ask(int x){int an=0;while(x)an+=sum[x],x-=x&-x;return an;} 16 17 inline int getid(int x){return lower_bound(has+1,has+cnt+1,x)-has;} 18 19 int main(){ 20 scanf("%d",&t); 21 while(t--) 22 { 23 scanf("%d",&nn),ed=hed=0; 24 memset(sum,0,sizeof(sum)); 25 F(i,1,nn) 26 { 27 scanf("%d%d%d%d",&x1,&y1,&x2,&y2); 28 has[++hed]=x1,has[++hed]=x2,has[++hed]=y1,has[++hed]=y2; 29 if(x1==x2)s[++ed].x=x1,s[ed].op=2,s[ed].l=min(y1,y2),s[ed].r=max(y2,y1); 30 else{ 31 s[++ed].x=min(x1,x2),s[ed].op=1,s[ed].l=y1,s[ed].r=y1; 32 s[++ed].x=max(x1,x2),s[ed].op=3,s[ed].l=y2,s[ed].r=y2; 33 } 34 } 35 sort(has+1,has+1+hed),cnt=unique(has+1,has+1+hed)-has,n=hed; 36 F(i,1,ed)s[i].x=getid(s[i].x),s[i].l=getid(s[i].l),s[i].r=getid(s[i].r); 37 sort(s+1,s+1+ed); 38 ll ans=0; 39 F(i,1,ed)if(s[i].op==1)add(s[i].l,1); 40 else if(s[i].op==2)ans+=ask(s[i].r)-ask(s[i].l-1); 41 else add(s[i].r,-1); 42 printf("%lld ",ans); 43 } 44 return 0; 45 }