zoukankan      html  css  js  c++  java
  • 线段树 + 扫描线

    线段树 + 扫描线 - 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 ----
  • 相关阅读:
    pyspark使用及原理
    谷歌地图聚合点使用(GoogleMaps MarkerCluster)
    struts2升级到2.5的配置
    二进制反码补码
    进制转换
    JAVA基础第一章
    TypeError: unhashable type: 'list' 如何解决?
    剪辑模板
    Mysql三天入门(三) 数据库设计的三范式
    Mysql三天入门(三) DBA命令
  • 原文地址:https://www.cnblogs.com/popodynasty/p/13975067.html
Copyright © 2011-2022 走看看