HDU 1255 覆盖的面积

覆盖的面积

Time Limit: 5000ms
Memory Limit: 32768KB
This problem will be judged on HDU. Original ID: 1255
64-bit integer IO format: %I64d      Java class name: Main
给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积.


 

Input

输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据的第一行是一个正整数N(1<=N<=1000),代表矩形的数量,然后是N行数据,每一行包含四个浮点数,代表平面上的一个矩形的左上角坐标和右下角坐标,矩形的上下边和X轴平行,左右边和Y轴平行.坐标的范围从0到100000.

注意:本题的输入数据较多,推荐使用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\n",ret);
81     }
82     return 0;
83 }
View Code

 

posted @ 2015-05-08 15:58  狂徒归来  阅读(159)  评论(0编辑  收藏  举报