线段树 + 扫描线

线段树 + 扫描线 - HDU 1255 - 覆盖的面积

对于每个区间结点,建立两个变量len1,len2

  • len1表示区间内被覆盖过一次且仅以次的线段长度
  • len2表示区间内被覆盖过大于等于两次的线段长度

因此,对于叶子结点:

if(l+1==r){
        if(cover[rt]==1){
            tree[rt].len1 = ordy[r]-ordy[l];
            tree[rt].len2 = 0;
        }else if(cover[rt] >= 2){
            tree[rt].len1 = 0;
            tree[rt].len2 = ordy[r] - ordy[l];
        }else{
            tree[rt].len1 = tree[rt].len2 = 0;
        }
        return;
}

对于非叶子节点

if(cover[rt] >= 2){
        tree[rt].len1 = 0;
        tree[rt].len2 = ordy[r] - ordy[l];
    }else if(cover[rt] == 1){
        tree[rt].len2 = tree[rt<<1].len1 + tree[rt<<1|1].len1 + tree[rt<<1].len2 + tree[rt<<1|1].len2;
        tree[rt].len1 = ordy[r]-ordy[l]-tree[rt].len2;
    }else{
        tree[rt].len1 = tree[rt<<1].len1 + tree[rt<<1|1].len1;
        tree[rt].len2 = tree[rt<<1].len2 + tree[rt<<1|1].len2;
}

完整代码

#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
#define EPS 1e-9
const int N = 1000+50;

bool equals(double a,double b){
    return fabs(a-b) < EPS;
}

struct node{
    double len1; // 当前区间仅被覆盖过一次
    double len2; // 当前区间至少被覆盖过两次的长度
    node(){len1=0;len2=0;}
};

struct SL{
    double x,upy,downy;
    int d;
    SL(){}
    SL(double a,double b,double c,int d)
        :x(a),upy(b),downy(c),d(d){}
    bool operator<(SL&m){
        if(!equals(x,m.x))
        return x < m.x;
        else return d > m.d;
    }
};



int my_unique(double arr[],int arrlen){
    arr[0]=arr[1]-1;
    int ptr = 0;
    for(int i = 1; i <= arrlen; i++){
        if(equals(arr[i],arr[i-1])){
            continue;
        }else{
            arr[++ptr] = arr[i];
        }
    }
    return ptr;
}

int my_lower_bound(double arr[],int len,double val){ // 找到第一个大于等于val的值 ,如果大于等于val,r=mid
    int l = 1,r = len;
    while(l < r){
        int mid = l+r>>1;
        if(equals(arr[mid],val) || arr[mid] >= val){
            r = mid;
        }else{
            l = mid+1;
        }
    }
    return l;
}
int cnt;
int len;
SL SLarr[N<<1];
double ordy[N<<1];
int cover[N<<3];
node tree[N<<3];

void push_up(int l,int r,int rt){
    if(l+1==r){
        if(cover[rt]==1){
            tree[rt].len1 = ordy[r]-ordy[l];
            tree[rt].len2 = 0;
        }else if(cover[rt] >= 2){
            tree[rt].len1 = 0;
            tree[rt].len2 = ordy[r] - ordy[l];
        }else{
            tree[rt].len1 = tree[rt].len2 = 0;
        }
        return;
    }

    if(cover[rt] >= 2){
        tree[rt].len1 = 0;
        tree[rt].len2 = ordy[r] - ordy[l];
    }else if(cover[rt] == 1){
        tree[rt].len2 = tree[rt<<1].len1 + tree[rt<<1|1].len1 + tree[rt<<1].len2 + tree[rt<<1|1].len2;
        tree[rt].len1 = ordy[r]-ordy[l]-tree[rt].len2;
    }else{
        tree[rt].len1 = tree[rt<<1].len1 + tree[rt<<1|1].len1;
        tree[rt].len2 = tree[rt<<1].len2 + tree[rt<<1|1].len2;
    }
}
void update(int l,int r,int rt,int ul,int ur,int d){
    if(ul <= l && ur >= r){
        cover[rt] += d;
        push_up(l,r,rt);
    }else{
        if(l+1==r)return;
        int mid = l+r>>1;
        if(ul <= mid){
            update(l,mid,rt<<1,ul,ur,d);
        }
        if(ur > mid){
            update(mid,r,rt<<1|1,ul,ur,d);
        }
        push_up(l,r,rt);
    }
}

void clear(int l,int r,int rt){
    tree[rt].len1 = tree[rt].len2 = 0;
    cover[rt] = 0;
    if(l+1==r)return;
    int mid = l+r>>1;
    clear(l,mid,rt<<1);
    clear(mid,r,rt<<1|1);
}
int main(){
    int T;
    scanf("%d",&T);
    for(int t = 1; t <= T; t++){
        int n;
        double xa,ya,xb,yb;
        scanf("%d",&n);
        cnt=len=0;
        for(int i = 1;i <= n; i++){
            scanf("%lf%lf%lf%lf",&xa,&ya,&xb,&yb);
            SLarr[++cnt] = SL(xa,yb,ya,1);
            ordy[cnt] = ya;
            SLarr[++cnt] = SL(xb,yb,ya,-1);
            ordy[cnt] = yb; 
        }

        sort(ordy+1,ordy+1+cnt);
        sort(SLarr+1,SLarr+1+cnt);

        len = my_unique(ordy,cnt);
        clear(1,len,1);
        double ans = 0.00;
        for(int i = 1; i <= cnt; i++){
            ans += tree[1].len2 * (SLarr[i].x-SLarr[i-1].x);
            int ul = my_lower_bound(ordy,len,SLarr[i].downy);
            int ur = my_lower_bound(ordy,len,SLarr[i].upy);
            update(1,len,1,ul,ur,SLarr[i].d);
        }

        printf("%.2f
",ans);
    }

    system("pause");
    return 0;
}

---- suffer now and live the rest of your life as a champion ----
原文地址:https://www.cnblogs.com/popodynasty/p/13975067.html