HDU 1255 覆盖的面积(线段树:扫描线求面积并)
Posted Yeader
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 1255 覆盖的面积(线段树:扫描线求面积并)相关的知识,希望对你有一定的参考价值。
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1255
题目大意:给你若干个矩形,让你求这些矩形重叠两次及以上的部分的面积。
解题思路:模板题,跟HDU 1542 Atlantis一样是求面积并,唯一的差别是这题要求的是重叠两次以上的面积,只要将cnt>0的条件改为cnt>1即可。
代码:
1 #include<cstdio> 2 #include<cmath> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 #include<vector> 7 #include<queue> 8 #include<set> 9 #include<map> 10 #include<stack> 11 #include<string> 12 #define LC(a) (a<<1) 13 #define RC(a) (a<<1|1) 14 #define MID(a,b) ((a+b)>>1) 15 using namespace std; 16 typedef long long LL; 17 const int INF=0x3f3f3f3f; 18 const int N=2e3+5; 19 20 struct node{ 21 double x1,x2,h,flag; 22 node(){} 23 node(double a,double b,double c,double d){ 24 x1=a;x2=b;h=c;flag=d; 25 } 26 }a[N]; 27 28 struct Node{ 29 int l,r,cnt; 30 double sum; 31 }tree[4*N]; 32 33 double X[N]; 34 35 bool cmp(node a,node b){ 36 return a.h<b.h; 37 } 38 39 int bin_search(double num,int l,int r){ 40 while(l<=r){ 41 int mid=(l+r)/2; 42 if(X[mid]==num) 43 return mid; 44 else if(X[mid]<num) 45 l=mid+1; 46 else 47 r=mid-1; 48 } 49 } 50 51 void pushup(int p){ 52 tree[p].cnt=(tree[LC(p)].cnt==tree[RC(p)].cnt?tree[LC(p)].cnt:-1); 53 tree[p].sum=tree[LC(p)].sum+tree[RC(p)].sum; 54 } 55 56 void pushdown(int p){ 57 tree[LC(p)].cnt=tree[RC(p)].cnt=tree[p].cnt; 58 //由cnt>0改为cnt>1 59 if(tree[p].cnt<=1) 60 tree[LC(p)].sum=tree[RC(p)].sum=0; 61 else{ 62 tree[LC(p)].sum=X[tree[LC(p)].r+1]-X[tree[LC(p)].l]; 63 tree[RC(p)].sum=X[tree[RC(p)].r+1]-X[tree[RC(p)].l]; 64 } 65 } 66 67 void build(int p,int l,int r){ 68 tree[p].l=l; 69 tree[p].r=r; 70 tree[p].cnt=0; 71 if(l==r){ 72 tree[p].sum=0; 73 return; 74 } 75 build(LC(p),l,MID(l,r)); 76 build(RC(p),MID(l,r)+1,r); 77 pushup(p); 78 } 79 80 void update(int p,int l,int r,int cnt){ 81 if(l>tree[p].r||r<tree[p].l) 82 return; 83 if(l<=tree[p].l&&r>=tree[p].r&&tree[p].cnt!=-1){ 84 tree[p].cnt+=cnt; 85 if(tree[p].cnt>=2) 86 tree[p].sum=X[tree[p].r+1]-X[tree[p].l]; 87 else 88 tree[p].sum=0; 89 return; 90 } 91 if(tree[p].cnt!=-1) 92 pushdown(p); 93 update(LC(p),l,r,cnt); 94 update(RC(p),l,r,cnt); 95 pushup(p); 96 } 97 98 int main(){ 99 int T; 100 scanf("%d",&T); 101 while(T--){ 102 int n; 103 scanf("%d",&n); 104 int m1=0,m2=1; 105 for(int i=1;i<=n;i++){ 106 double x1,y1,x2,y2; 107 scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); 108 X[++m1]=x1; 109 a[m1]=node(x1,x2,y1,1); 110 X[++m1]=x2; 111 a[m1]=node(x1,x2,y2,-1); 112 } 113 //横坐标离散化 114 sort(a+1,a+1+m1,cmp); 115 sort(X+1,X+1+m1); 116 for(int i=2;i<=m1;i++){ 117 if(X[i]!=X[i-1]) 118 X[++m2]=X[i]; 119 } 120 build(1,1,m2-1); 121 double ans=0; 122 //依次读入扫描线求重叠两次及以上的面积并 123 for(int i=1;i<=m1-1;i++){ 124 int l=bin_search(a[i].x1,1,m2); 125 int r=bin_search(a[i].x2,1,m2)-1; 126 update(1,l,r,a[i].flag); 127 ans+=tree[1].sum*(a[i+1].h-a[i].h); 128 } 129 printf("%.2lf\n",ans); 130 } 131 return 0; 132 }
以上是关于HDU 1255 覆盖的面积(线段树:扫描线求面积并)的主要内容,如果未能解决你的问题,请参考以下文章