标签:
题目:Counting Intersections
链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5862
题意:给出n 条平行于坐标轴的线段,问这些线段有多少交点(题目保证没有两条线段共享一个端点、保证没有重叠、保证线段长度大于0)n范围10万
思路:
将n 条线段2n 个点按x 排序,然后当遇到一个横向的左端点时,对应的y++,遇到右端点,y--,遇到竖线,交点数目加上 下端点到上端点 之间的y 的和。离散化加树状数组可做。要注意细节,排序的优先级要注意。我的做法是直接按x 排序,然后处理的时候相同x 的一起处理(分3 次,先把要加的全部加上,然后有询问就询问,最后才减,不这样的话,T形的就比较麻烦了)
AC代码:
1 #include<stdio.h> 2 #include<map> 3 #include<string.h> 4 #include<algorithm> 5 using namespace std; 6 #define LL long long 7 struct Point 8 { 9 int x,y; 10 int yy; 11 bool left; 12 bool type; 13 }; 14 Point v[200020]; 15 int vo; 16 bool cmp1(Point x,Point y) 17 { 18 return x.x<y.x; 19 } 20 bool cmp2(Point x,Point y) 21 { 22 return x.y<y.y; 23 } 24 int c[200020]; 25 int Lowbit(int x) 26 { 27 return x&(-x); 28 } 29 int getsum(int pos) 30 { 31 int sum=0; 32 while(pos>0) 33 { 34 sum+=c[pos]; 35 pos-=Lowbit(pos); 36 } 37 return sum; 38 } 39 void update(int pos,int num,int n) 40 { 41 while(pos<=n) 42 { 43 c[pos]+=num; 44 pos+=Lowbit(pos); 45 } 46 } 47 map<int,int> mp; 48 int main() 49 { 50 int t,n; 51 scanf("%d",&t); 52 while(t--) 53 { 54 mp.clear(); 55 scanf("%d",&n); 56 vo=0; 57 for(int i=0;i<n;i++) 58 { 59 scanf("%d%d%d%d",&v[vo].x,&v[vo].y,&v[vo+1].x,&v[vo+1].y); 60 vo+=2; 61 v[vo-2].type=v[vo-1].type= v[vo-2].x==v[vo-1].x; //ÊúµÄÊÇ 1 62 if(v[vo-2].type==1 && v[vo-2].y>v[vo-1].y) swap(v[vo-2],v[vo-1]); 63 64 else if(v[vo-2].type==0 && v[vo-2].x>v[vo-1].x) swap(v[vo-2],v[vo-1]); 65 v[vo-2].left=1 , v[vo-1].left=0; 66 v[vo-2].yy=v[vo-1].y; 67 } 68 sort(v,v+vo,cmp2); 69 int y=1; 70 for(int i=1;i<vo;i++) 71 { 72 if( v[i].y==v[i-1].y ) mp[v[i-1].y]=y,v[i-1].y=y; 73 else mp[v[i-1].y]=y,v[i-1].y=y++; 74 } 75 mp[v[vo-1].y]=y; 76 v[vo-1].y=y; 77 sort(v,v+vo,cmp1); 78 memset(c,0,sizeof(c)); 79 LL ans=0; 80 int flag=-1; 81 for(int i=0;i<vo;i++) 82 { 83 flag=vo-1; 84 for(int j=i;j<vo;j++) 85 { 86 87 if(v[j].x==v[i].x && v[j].left==1 && v[j].type==0) 88 { 89 update(v[j].y,1,y); 90 } 91 else if(v[j].x!=v[i].x) 92 { 93 flag=j-1; 94 break; 95 } 96 } 97 for(int j=i;j<=flag;j++) 98 { 99 if(v[j].left==1 && v[j].type==1) 100 { 101 //printf("== %d %d %d %d %d\n",v[j].x,v[j].y,v[j].type,v[j].left,v[j].yy); 102 ans+=getsum(mp[v[j].yy])-getsum(v[j].y-1); 103 } 104 } 105 for(int j=i;j<=flag;j++) 106 { 107 if(v[j].left==0 && v[j].type==0) 108 { 109 update(v[j].y,-1,y); 110 } 111 } 112 i=flag; 113 } 114 printf("%I64d\n",ans); 115 } 116 return 0; 117 }
HDU 5862 Counting Intersections
标签:
原文地址:http://www.cnblogs.com/hchlqlz-oj-mrj/p/5785342.html