题目地址:poj1151(Atlantis)& hdu1542 (Atlantis)
题目大意:
给你N个矩形,求出矩形在平面图构成的面积。
解题思路:
线段数+扫描线。
需要注意:
记住线段树返回的cnt 是从左往右每条扫描线 投影Y轴的长度,就能很好的理解线段数+扫描线的代码。
推荐博客:线段树辅助——扫描线法计算矩形面积并,这个博客说的是从下到上扫描,离散化x坐标,原理是一样的,我的代码是从左往右扫描,离散化Y坐标以Y坐标建树。
代码:
1 #include <algorithm> 2 #include <iostream> 3 #include <sstream> 4 #include <cstdlib> 5 #include <cstring> 6 #include <cstdio> 7 #include <string> 8 #include <bitset> 9 #include <vector> 10 #include <queue> 11 #include <stack> 12 #include <cmath> 13 #include <list> 14 #include <map> 15 #include <set> 16 using namespace std; 17 /***************************************/ 18 #define ll long long 19 #define int64 __int64 20 /***************************************/ 21 const int INF = 0x7f7f7f7f; 22 const double eps = 1e-8; 23 const double PIE=acos(-1.0); 24 const int d1x[]= {0,-1,0,1}; 25 const int d1y[]= {-1,0,1,0}; 26 const int d2x[]= {0,-1,0,1}; 27 const int d2y[]= {1,0,-1,0}; 28 const int fx[]= {-1,-1,-1,0,0,1,1,1}; 29 const int fy[]= {-1,0,1,-1,1,-1,0,1}; 30 /***************************************/ 31 void openfile() 32 { 33 freopen("data.in","rb",stdin); 34 freopen("data.out","wb",stdout); 35 } 36 /**********************华丽丽的分割线,以上为模板部分*****************/ 37 const int M=300; 38 39 struct tree 40 { 41 int left,right; //左右区间 42 double turel,turer,cnt; //记录左右区间的真实值和 投影Y轴坐标的覆盖的程度cnt 43 int c; //记录该区间被覆盖几次。 44 45 } node[M*4]; 46 struct Line 47 { 48 double x,y1,y2; //记录每一条扫描线 49 int f; //标记入边1,出边为-1 50 }line[M]; //储存所有的线段 51 int cnt; 52 double y[M]; //将y的坐标记录然后离散化 53 bool cmp(Line a,Line b) //排序 54 { 55 return a.x<b.x; 56 } 57 void build__tree(int id,int l,int r) //初始化树 58 { 59 int mid=(l+r)/2; 60 node[id].turel=y[l]; 61 node[id].turer=y[r]; 62 node[id].left=l; 63 node[id].right=r; 64 node[id].cnt=0; 65 node[id].c=0; 66 if (l+1==r) 67 return ; 68 build__tree(id*2,l,mid); 69 build__tree(id*2+1,mid,r); 70 } 71 void upcnt(int id) //更新投影Y轴的线段 72 { 73 if (node[id].c>0) 74 { 75 node[id].cnt=node[id].turer-node[id].turel; 76 return ; 77 } 78 if (node[id].left+1==node[id].right) 79 node[id].cnt=0; 80 else 81 node[id].cnt=node[id*2].cnt+node[id*2+1].cnt; 82 } 83 void updata(int id,Line v) 84 { 85 if (node[id].turel==v.y1&&node[id].turer==v.y2) 86 { 87 node[id].c+=v.f; 88 upcnt(id); 89 return ; 90 } 91 if (v.y2<=node[id*2].turer) 92 updata(id*2,v); 93 else if (v.y1>=node[id*2+1].turel) 94 updata(id*2+1,v); 95 else 96 { 97 Line tmp; 98 tmp=v; 99 tmp.y2=node[id*2].turer; 100 updata(id*2,tmp); 101 tmp=v; 102 tmp.y1=node[id*2+1].turel; 103 updata(id*2+1,tmp); 104 } 105 upcnt(id); 106 } 107 108 int main() 109 { 110 int n; 111 int icas=0; 112 while(scanf("%d",&n)&&n) 113 { 114 int i,j; 115 int d=1; 116 for(i=1;i<=n;i++) 117 { 118 double x1,x2,y1,y2; 119 scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); 120 line[d].x=x1; 121 line[d].y1=y1; 122 line[d].y2=y2; 123 line[d].f=1; 124 y[d]=y1; 125 d++; 126 line[d].x=x2; 127 line[d].y1=y1; 128 line[d].y2=y2; 129 line[d].f=-1; 130 y[d]=y2; 131 d++; 132 } 133 sort(y+1,y+d); 134 sort(line+1,line+d,cmp); 135 build__tree(1,1,d-1); 136 updata(1,line[1]); 137 double sum=0; 138 for(i=2;i<d;i++) 139 { 140 sum+=node[1].cnt*(line[i].x-line[i-1].x); 141 updata(1,line[i]); 142 } 143 printf("Test case #%d ",++icas); 144 printf("Total explored area: %.2lf ",sum); 145 } 146 return 0; 147 }