codevs3044 矩形面积求并 线段树+扫描线

题意:给定N个矩形,求复数个矩形所覆盖的面积和

题解:

 

首先我们离散化,然后按照纵坐标从下往上扫,每扫到一条边,就把这条边的边权压入线段树——规定始边边权为1,终边边权为-1

每次从下往上枚举一条边,将每两个坐标之间的间隔看成是一个点,每次枚举看那个间隔权值>1,统计下来,乘以两条边之间的距离。

当然枚举间隔的时候不必全扫一边,如果一个区间的和为零,直接return

#include <map>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;

const int MAXN=100+2;
struct LINE{
    int t;
    double sx,tx,y;
    LINE(){}
    LINE(int _t,double _sx,double _tx,double _y):t(_t),sx(_sx),tx(_tx),y(_y){}
}line[2*MAXN];
typedef struct NODE{
    int l,r,s,add;
    NODE *lchild,*rchild;
    NODE(){}
    NODE(int _l,int _r):l(_l),r(_r),s(0),add(0),lchild(0),rchild(0){}
} *TREE;
TREE root;
int N,M,b[2*MAXN];
double x1,x2,y1,y2,ans,width,a[2*MAXN],l[2*MAXN];
map<double,int> table;

bool cmp1(LINE a,LINE b){ return a.y<b.y;}

bool cmp2(int x,int y){ return a[x]<a[y];}

void Pushup(TREE &x){ x->s=x->lchild->s+x->rchild->s;}

void Pushdown(TREE &x,int m){
    if(x->add){
        x->lchild->s+=x->add*(m-(m>>1));
        x->rchild->s+=x->add*(m>>1);
        x->lchild->add+=x->add,x->rchild->add+=x->add,x->add=0;
    }
}

void Build(TREE &x,int l,int r){
    x=new NODE(l,r);
    if(l==r) return;

    int m=(l+r)>>1;
    Build(x->lchild,l,m),Build(x->rchild,m+1,r);
}

void Update(TREE &x,int l,int r,int v){
    if(x->l>=l && x->r<=r){
        x->add+=v,x->s+=v*(x->r-x->l+1);
        return;
    }

    Pushdown(x,x->r-x->l+1);

    int m=(x->l+x->r)>>1;
    if(l<=m) Update(x->lchild,l,r,v);
    if(r>m) Update(x->rchild,l,r,v);

    Pushup(x);
}

bool Query(TREE &x,int p){
    if(x->l==x->r) return x->s;

    Pushdown(x,x->r-x->l+1);

    if(!x->s) return 0;

    int m=(x->l+x->r)>>1;
    if(p<=m) return Query(x->lchild,p);
    return Query(x->rchild,p);
}

void Erase(TREE &x){
    if(!x) return;
    Erase(x->lchild),Erase(x->rchild);
    delete x;
}

int main(){
    while(scanf("%d",&N)!=EOF){
        if(!N) break;

        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        memset(l,0,sizeof(l));
        memset(line,0,sizeof(line));
        table.clear(),M=0;

        for(int i=1;i<=N;i++){
            cin >> x1 >> y1 >> x2 >> y2;
            line[++M]=LINE(1,x1,x2,y1),a[M]=x1,b[M]=M;
            line[++M]=LINE(-1,x1,x2,y2),a[M]=x2,b[M]=M;
        }
        sort(line+1,line+M+1,cmp1);
        sort(b+1,b+M+1,cmp2);

        N=0;
        for(int i=1,t=0;i<=M;i++)
            if(!t || a[b[i]]!=a[b[t]])
                table[a[b[i]]]=++N,l[N]=a[b[i]]-a[b[t]],t=i;

        Build(root,1,N),ans=width=0;
        for(int i=1;i<=M;i++){
            ans+=(line[i].y-line[i-1].y)*width;

            if(table[line[i].sx]+1<=table[line[i].tx])
                Update(root,table[line[i].sx]+1,table[line[i].tx],line[i].t);

            width=0;
            for(int j=2;j<=N;j++)
                if(Query(root,j)) width+=l[j];
        }
        printf("%.2lf\n",ans);

        Erase(root);
    }

    return 0;
}
View Code

 

posted @ 2017-02-26 13:06  WDZRMPCBIT  阅读(228)  评论(0编辑  收藏  举报