覆盖的面积
Time Limit: 5000ms
Memory Limit: 32768KB
This problem will be judged on HDU. Original ID: 125564-bit integer IO format: %I64d Java class name: Main
给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积.
Input
输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据的第一行是一个正整数N(1<=N<=1000),代表矩形的数量,然后是N行数据,每一行包含四个浮点数,代表平面上的一个矩形的左上角坐标和右下角坐标,矩形的上下边和X轴平行,左右边和Y轴平行.坐标的范围从0到100000.
注意:本题的输入数据较多,推荐使用scanf读入数据.
注意:本题的输入数据较多,推荐使用scanf读入数据.
Output
对于每组测试数据,请计算出被这些矩形覆盖过至少两次的区域的面积.结果保留两位小数.
Sample Input
2 5 1 1 4 2 1 3 3 7 2 1.5 5 4.5 3.5 1.25 7.5 4 6 3 10 7 3 0 0 1 1 1 0 2 1 2 0 3 1
Sample Output
7.63 0.00
解题:离散化,扫面线求矩形面积的交。。关键是如何更新覆盖两次以上的区间。
如果当前区间覆盖次数超过一次,那么区间长度就是差了,如果覆盖次数是1呢,那么看左儿子与右儿子,覆盖至少一次的长度,这两个加起来,即覆盖至少两次的长度。。。。
其余的跟一般的求面积并没什么区别了。。。
ps:此题的题面貌似有误,应该是先左下角,再右上角,还有第一个样例保留两位小数貌似是7.62.。。
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn = 100000; 4 struct node{ 5 int lt,rt,cover; 6 double s,ss; 7 }tree[maxn<<2]; 8 struct Line{ 9 double x1,x2,y; 10 int delta; 11 Line(){} 12 Line(double xx,double xxx,double yy,int dt){ 13 x1 = xx; 14 x2 = xxx; 15 y = yy; 16 delta = dt; 17 } 18 bool operator<(const Line &t)const{ 19 return y < t.y; 20 } 21 }; 22 vector<Line>line; 23 vector<double>d; 24 void build(int lt,int rt,int v){ 25 tree[v].lt = lt; 26 tree[v].rt = rt; 27 tree[v].cover = 0; 28 tree[v].s = tree[v].ss = 0; 29 if(lt + 1 == rt) return; 30 int mid = (lt + rt)>>1; 31 build(lt,mid,v<<1); 32 build(mid,rt,v<<1|1); 33 } 34 void pushUp(int v){ 35 if(tree[v].cover) tree[v].s = d[tree[v].rt] - d[tree[v].lt]; 36 else if(tree[v].lt + 1 == tree[v].rt) tree[v].s = 0; 37 else tree[v].s = tree[v<<1].s + tree[v<<1|1].s; 38 39 if(tree[v].cover > 1) tree[v].ss = d[tree[v].rt] - d[tree[v].lt]; 40 else if(tree[v].lt + 1 == tree[v].rt) tree[v].ss = 0; 41 else if(tree[v].cover == 1) tree[v].ss = tree[v<<1].s + tree[v<<1|1].s; 42 else tree[v].ss = tree[v<<1].ss + tree[v<<1|1].ss; 43 } 44 void update(int lt,int rt,int delta,int v){ 45 if(lt <= tree[v].lt && rt >= tree[v].rt){ 46 tree[v].cover += delta; 47 pushUp(v); 48 return; 49 } 50 if(lt < tree[v<<1].rt) update(lt,rt,delta,v<<1); 51 if(rt > tree[v<<1|1].lt) update(lt,rt,delta,v<<1|1); 52 pushUp(v); 53 } 54 int main(){ 55 int T,n; 56 double x1,y1,x2,y2; 57 scanf("%d",&T); 58 while(T--){ 59 scanf("%d",&n); 60 line.clear(); 61 d.clear(); 62 for(int i = 0; i < n; ++i){ 63 scanf("%lf %lf %lf %lf",&x1,&y1,&x2,&y2); 64 d.push_back(x1); 65 d.push_back(x2); 66 line.push_back(Line(x1,x2,y1,1)); 67 line.push_back(Line(x1,x2,y2,-1)); 68 } 69 sort(line.begin(),line.end()); 70 sort(d.begin(),d.end()); 71 d.erase(unique(d.begin(),d.end()),d.end()); 72 double ret = 0; 73 build(0,d.size()-1,1); 74 for(int i = 0; i < line.size(); ++i){ 75 if(i) ret += (line[i].y - line[i-1].y)*tree[1].ss; 76 int x = lower_bound(d.begin(),d.end(),line[i].x1)-d.begin(); 77 int y = lower_bound(d.begin(),d.end(),line[i].x2)-d.begin(); 78 update(x,y,line[i].delta,1); 79 } 80 printf("%.2f ",ret); 81 } 82 return 0; 83 }