hdu 1542 Atlantis
题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=1542
题目大意:线段树+扫描线+面积并
注释:1.偶是菜鸟狗,从大牛那里copy过来的代码模板。
2.推荐线段树求面积并的地址:http://www.cnblogs.com/ka200812/archive/2011/11/13/2247064.html
1 #include<iostream> 2 #include<string> 3 #include<algorithm> 4 #include<cstdio> 5 using namespace std; 6 7 struct node 8 { 9 int l; 10 int r; 11 int cover; 12 double len; 13 }; 14 15 node tree[2000]; 16 double yy[250]; 17 int n,len; 18 19 struct Line 20 { 21 double y_down; 22 double y_up; 23 double x; 24 int cover; 25 }; 26 27 Line line[250]; 28 29 int cmp(Line a,Line b) 30 { 31 return a.x<b.x; 32 } 33 34 int find(double x) 35 { 36 int l=0,r=len,mid;//左闭右闭区间的二分 37 while(l<=r) 38 { 39 mid=(l+r)/2; 40 if(yy[mid]==x) 41 return mid; 42 if(yy[mid]<x) 43 l=mid+1; 44 else 45 r=mid-1; 46 } 47 return l; 48 } 49 50 void build(int i,int l,int r) 51 { 52 tree[i].l=l; 53 tree[i].r=r; 54 tree[i].cover=0; 55 tree[i].len=0; 56 if(l+1==r) 57 return; 58 int mid=(l+r)/2; 59 build(2*i,l,mid); 60 build(2*i+1,mid,r); 61 } 62 63 void fun(int i) 64 { 65 if(tree[i].cover) 66 tree[i].len=yy[tree[i].r]-yy[tree[i].l]; //如果cover大于1,那么整段都可用于与下一线段求并面积 67 else if(tree[i].l+1==tree[i].r) //叶子线段 68 tree[i].len=0; 69 else 70 tree[i].len=tree[2*i].len+tree[2*i+1].len; //很简单的dp 71 } 72 73 void updata(int i,int l,int r,int cover) 74 { 75 if(tree[i].l>=r || tree[i].r<=l) 76 return; 77 if(tree[i].l>=l && tree[i].r<=r) 78 { 79 tree[i].cover+=cover; 80 fun(i); 81 return; 82 } 83 updata(2*i,l,r,cover); 84 updata(2*i+1,l,r,cover); 85 fun(i); 86 } 87 88 int main() 89 { 90 double x1,y1,x2,y2; 91 int i,m,a,b,cas=1; 92 //freopen("in.txt","r",stdin); 93 while(scanf("%d",&n)==1 && n) 94 { 95 m=0; 96 for(i=0;i<n;i++) 97 { 98 scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); 99 yy[m]=y1; 100 line[m].cover=1; 101 line[m].x=x1; 102 line[m].y_down=y1; 103 line[m++].y_up=y2; 104 105 yy[m]=y2; 106 line[m].cover=-1; 107 line[m].x=x2; 108 line[m].y_down=y1; 109 line[m++].y_up=y2; 110 } 111 sort(yy,yy+m); 112 len=1; 113 for(i=1;i<m;i++) 114 { 115 if(yy[i-1]!=yy[i]) 116 yy[len++]=yy[i];//去除相同的点 117 } 118 len--;//新的yy数组下标还是从0开始的 119 build(1,0,len); 120 sort(line,line+m,cmp); 121 double ans=0; 122 printf("Test case #%d\n",cas++); 123 for(i=0;i<m-1;i++) 124 { 125 a=find(line[i].y_down); 126 b=find(line[i].y_up); 127 updata(1,a,b,line[i].cover); 128 ans+=tree[1].len*(line[i+1].x-line[i].x); //tree[1].len已经保留了整个树与line[i+1]所能求并面积的长度 129 } 130 printf("Total explored area: %0.2lf\n\n",ans); 131 } 132 return 0; 133 }