【 HDU 1255】 覆盖的面积(矩阵面积交,线段树,扫描法)

【题目】

覆盖的面积

 

Problem Description
给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积.

 

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

 

Author
Ignatius.L & weigang Lee
 
 
【分析】
  跟矩阵面积并差不多吧。
  不过不要直接改成cnt>=2就交了哦
  如果这个区间完全覆盖只有1,但是子树有完全覆盖的1,那也是可以的哦~
 
  感觉如果问覆盖k次,我还要开个k的数组ORZ。。。
 
  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<cmath>
  7 using namespace std;
  8 #define Maxn 100010
  9 
 10 struct hp
 11 {
 12     int x1,x2,flag;
 13     double y;
 14 }t[Maxn*2];int tl;
 15 struct lsh
 16 {
 17     double x;
 18     int id;
 19 }q[Maxn*2];int ql;
 20 
 21 bool cmp(lsh x,lsh y) {return x.x<y.x;}
 22 bool cmp2(hp x,hp y) {return x.y<y.y;}
 23 
 24 int mymin(int x,int y) {return x<y?x:y;}
 25 
 26 double dis[2*Maxn];
 27 
 28 struct node
 29 {
 30     int l,r,lc,rc,cnt;
 31     double sm,fg;
 32 }tr[Maxn*2];int len;
 33 int build(int l,int r)
 34 {
 35     int x=++len;
 36     tr[x].l=l;tr[x].r=r;
 37     tr[x].sm=tr[x].cnt=0;tr[x].fg=0;
 38     if(l<r-1)
 39     {
 40         int mid=(tr[x].l+tr[x].r)>>1;
 41         tr[x].lc=build(l,mid);
 42         tr[x].rc=build(mid,r);
 43     }
 44     else tr[x].lc=tr[x].rc=0;
 45     return x;
 46 }
 47 
 48 void upd(int x)
 49 {
 50     int l=tr[x].l,r=tr[x].r,lc=tr[x].lc,rc=tr[x].rc;
 51     if(tr[x].cnt!=0) tr[x].fg=dis[r]-dis[l];
 52     else tr[x].fg=tr[lc].fg+tr[rc].fg;
 53     if(tr[x].cnt>=2) tr[x].sm=dis[r]-dis[l];
 54     else if(tr[x].cnt==1) tr[x].sm=tr[lc].fg+tr[rc].fg;
 55     else tr[x].sm=tr[lc].sm+tr[rc].sm;
 56 }
 57 
 58 void change(int x,int l,int r,int c)
 59 {
 60     if(tr[x].l==l&&tr[x].r==r)
 61     {
 62         tr[x].cnt+=c;
 63         upd(x);
 64         return;
 65     }
 66     int mid=(tr[x].l+tr[x].r)>>1;
 67     if(r<=mid) change(tr[x].lc,l,r,c);
 68     else if(l>=mid) change(tr[x].rc,l,r,c);
 69     else
 70     {
 71         change(tr[x].lc,l,mid,c);
 72         change(tr[x].rc,mid,r,c);
 73     }
 74     upd(x);
 75 }
 76 
 77 int main()
 78 {
 79     int T;
 80     int n;
 81     scanf("%d",&T);
 82     while(T--)
 83     {
 84         scanf("%d",&n);
 85         if(n==0) break;
 86         tl=0;ql=0;
 87         for(int i=1;i<=n;i++)
 88         {
 89             double x1,y1,x2,y2;
 90             scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
 91             //t[++tl].x1,
 92             t[++tl].flag=1;t[tl].y=y1;
 93             t[++tl].flag=-1;t[tl].y=y2;
 94             q[++ql].x=x1,q[ql].id=tl;
 95             q[++ql].x=x2,q[ql].id=tl+2*n;
 96         }
 97         sort(q+1,q+1+ql,cmp);
 98         int p=0;
 99         for(int i=1;i<=ql;i++)
100         {
101             if(q[i].x!=q[i-1].x||p==0) p++,dis[p]=dis[p-1]+q[i].x-q[i-1].x;
102             if(q[i].id<=2*n) t[q[i].id].x1=t[q[i].id-1].x1=p;
103             else t[q[i].id-2*n].x2=t[q[i].id-1-2*n].x2=p;
104         }
105         sort(t+1,t+1+tl,cmp2);
106         len=0;tr[0].sm=0;
107         build(1,p);
108         double ans=0;
109         for(int i=1;i<tl;i++)
110         {
111             // printf("%d %d\n",t[i].x1,t[i].x2);
112             change(1,t[i].x1,t[i].x2,t[i].flag);
113             ans+=tr[1].sm*(t[i+1].y-t[i].y);
114         }
115         printf("%.2lf\n",ans);
116         // printf("Test case #%d\nTotal explored area: %.2lf\n\n",++kase,ans);
117     }
118     return 0;
119 }
View Code

 

2016-11-10 14:37:49

  
posted @ 2016-11-10 14:33  konjak魔芋  阅读(803)  评论(0编辑  收藏  举报