【 HDU 1255】 覆盖的面积(矩阵面积交,线段树,扫描法)
【题目】
覆盖的面积
Problem Description给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积.
Input输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据的第一行是一个正整数N(1<=N<=1000),代表矩形的数量,然后是N行数据,每一行包含四个浮点数,代表平面上的一个矩形的左上角坐标和右下角坐标,矩形的上下边和X轴平行,左右边和Y轴平行.坐标的范围从0到100000.
注意:本题的输入数据较多,推荐使用scanf读入数据.
Output对于每组测试数据,请计算出被这些矩形覆盖过至少两次的区域的面积.结果保留两位小数.
Sample Input2 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 Output7.63 0.00
AuthorIgnatius.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 }
2016-11-10 14:37:49