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 }

 

 

 

posted @ 2017-10-02 13:01  Yeader  阅读(239)  评论(0编辑  收藏  举报