hdu1255扫描线计算覆盖两次面积

总体来说也是个模板题,但是要开两个线段树来保存被覆盖一次,两次的面积

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#include<algorithm>
#define maxn 10000
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
struct seg{
    double l,r,h;
    int s;
    seg(){}
    seg(double l,double r,double h,int s):l(l),r(r),h(h),s(s){}
    bool operator<(const seg & a)const{
        return h<a.h;
    }
}segs[maxn];
double data[maxn];
int tot,m;
double len1[maxn<<2],len2[maxn<<2];//区间被覆盖一次,被覆盖两次,len1[rt]+len2[rt]=data[r+1]-data[l] 
int cnt[maxn<<2];
inline void pushup(int rt,int l,int r){
    if(cnt[rt]>=2){
        len2[rt]=data[r+1]-data[l];
        len1[rt]=0;
    }
    else if(cnt[rt]==1){
        if(l==r) len2[rt]=0;
        else len2[rt]=len2[rt<<1]+len2[rt<<1|1]+len1[rt<<1]+len1[rt<<1|1];
        len1[rt]=data[r+1]-data[l]-len2[rt];
    }
    else {
        if(l==r) len1[rt]=len2[rt]=0;
        else {
            len1[rt]=len1[rt<<1]+len1[rt<<1|1];
            len2[rt]=len2[rt<<1]+len2[rt<<1|1];
        }
    }
    
}
void update(int L,int R,int c,int l,int r,int rt){
    if(L<=l && R>=r){
        cnt[rt]+=c;
        pushup(rt,l,r);
        return;
    }
    int m=l+r>>1;
    if(L<=m) update(L,R,c,lson);
    if(R>m) update(L,R,c,rson);
    pushup(rt,l,r);
}
void init(){
    tot=m=0;
    memset(data,0,sizeof data);
    memset(len1,0,sizeof len1);
    memset(cnt,0,sizeof cnt);
    memset(len2,0,sizeof len2); 
}
int main(){
    int T,n;
    cin >> T;
    while(T--){
        init();
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            double a,b,c,d;
            scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
            data[tot]=a;
            segs[tot++]=seg(a,c,b,1);
            data[tot]=c;
            segs[tot++]=seg(a,c,d,-1);
        }
        sort(segs,segs+tot);
        sort(data,data+tot);
        m=unique(data,data+tot)-data;
        double ans=0;
        for(int i=0;i<tot;i++){
            int L=lower_bound(data,data+m,segs[i].l)-data;
            int R=lower_bound(data,data+m,segs[i].r)-data-1;
            update(L,R,segs[i].s,0,m,1);
            ans+=len2[1]*(segs[i+1].h-segs[i].h);
        }
        printf("%.2lf\n",ans);
    }
    return 0;
}

 

posted on 2018-11-12 10:34  zsben  阅读(147)  评论(0编辑  收藏  举报

导航