hdu_5862_Counting Intersections(扫描线)

题目链接: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\n",ans);
43     }
44     return 0;
45 }
View Code

 

posted @ 2016-08-25 14:29  bin_gege  阅读(161)  评论(0编辑  收藏  举报