zoukankan      html  css  js  c++  java
  • POJ 1177:线段树 离散化 扫描线

    计算畸形区域的周长

    比面积的扫描要麻烦些,原因就在不重叠区域的处理,同一段高度可能要重复叠加

    所以线段树的结点里要多维护三个东西:

    times:区间里不重叠的区间数

    比如说第一个区间是1~5,第二个是2~6,,第三个是9~10,那前两个可以合成1~6,和第三个独立,则这个整体的times为2

    为了维护times,我们需要lbd和rbd两个变量,分别作为区间左右端点是否被覆盖的标志

    有的博客里把这两个变量写成了bool型,这些其实不好,在运算时会带来麻烦,我们直接用int 0和1表示会好些。这样只有在左孩子的rbd*右孩子的lbd!=0的时候才表示两孩子连接时会多一个覆盖次数

    感觉扫描线的题目最关键的就是即使把更新后的影响传递上去

    还有一个比较关键的东西就是离散化的理解

    我的离散化是:把每一个x及其与下一个x之间的区间看作一个整体

    比如1 5 8三个点

    离散化后,1表示1~5,2表示5~8

    应该可以注意到,只需要离散n-1个点,因为最后一个点的右边是没有长度的

    所以当线段树中一个结点的表示区间是1~2,那这个区间的长度应该是1~8(1~5+5~8)

    具体看代码

    #include"cstdio"
    #include"queue"
    #include"cmath"
    #include"stack"
    #include"iostream"
    #include"algorithm"
    #include"cstring"
    #include"queue"
    #include"map"
    #include"set"
    #include"vector"
    #define ll long long
    #define mems(a,b) memset(a,b,sizeof(a))
    #define ls pos<<1
    #define rs pos<<1|1
    
    using namespace std;
    const int MAXN = 1e5+50;
    const int MAXQ = 10050;
    const int INF = 0x3f3f3f3f;
    int n,m;
    int x[MAXN];
    
    struct Line{
        int l,r,h,w;
        Line(){}
        Line(int a,int b,int c,int d):l(a),r(b),h(c),w(d){}
    }line[MAXN];
    
    bool cmp(Line a,Line b){
        return a.h<b.h;
    }
    
    struct Node{
        int l,r;
        int len;
        int cnt;
        int times;
        int w;
        int lbd,rbd;
    }node[MAXN<<2];
    
    void build(int l,int r,int pos){
        node[pos].l=l;
        node[pos].r=r;
        node[pos].cnt=node[pos].w=node[pos].times=0;
        node[pos].lbd=node[pos].rbd=0;
        node[pos].len=x[node[pos].r+1]-x[node[pos].l];
        if(l==r) return;
        int mid=(l+r)>>1;
        build(l,mid,ls);
        build(mid+1,r,rs);
    }
    
    void pushup(int pos){
        if(node[pos].w>0){
            node[pos].cnt=node[pos].len;
            node[pos].lbd=node[pos].rbd=node[pos].times=1;
        }
        else if(node[pos].l==node[pos].r){
            node[pos].cnt=0;
            node[pos].lbd=node[pos].rbd=node[pos].times=0;
        }
        else{
            node[pos].cnt=node[ls].cnt+node[rs].cnt;
            node[pos].lbd=node[ls].lbd;
            node[pos].rbd=node[rs].rbd;
            node[pos].times=node[ls].times+node[rs].times-node[rs].lbd*node[ls].rbd;
        }
    }
    
    int get_pos(int w){
        int low=0,high=m,mid,ans;
        while(low<=high){
            mid=(low+high)>>1;
            if(x[mid]==w) return mid;
            else if(x[mid]>w) high=mid-1;
            else low=mid+1;
        }
    }
    
    void update(int l,int r,int pos,int w){
        if(l<=node[pos].l&&node[pos].r<=r){
            node[pos].w+=w;
            pushup(pos);
            return;
        }
        int mid=(node[pos].l+node[pos].r)>>1;
        if(l<=mid) update(l,r,ls,w);
        if(r>mid) update(l,r,rs,w);
        pushup(pos);
    }
    
    int main(){
        //freopen("in.txt","r",stdin);
        while(~scanf("%d",&n)){
            for(int i=0;i<2*n;i+=2){
                int x1,y1,x2,y2;
                scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
                line[i]=Line(x1,x2,y1,1);
                line[i+1]=Line(x1,x2,y2,-1);
                x[i]=x1;
                x[i+1]=x2;
            }
            sort(line,line+2*n,cmp);
            sort(x,x+2*n);
            m=0;
            for(int i=1;i<2*n;i++) if(x[i]!=x[i-1]) x[++m]=x[i];
            build(0,m-1,1);
            int ans=0;
            int pre=0;
            for(int i=0;i<2*n-1;i++){
                int l=get_pos(line[i].l);
                int r=get_pos(line[i].r)-1;
                update(l,r,1,line[i].w);
                ans+=2*node[1].times*(line[i+1].h-line[i].h);
                ans+=abs(node[1].cnt-pre);
                pre=node[1].cnt;
            }
            ans+=line[2*n-1].r-line[2*n-1].l;
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    LeetCode Path Sum II
    LeetCode Longest Palindromic Substring
    LeetCode Populating Next Right Pointers in Each Node II
    LeetCode Best Time to Buy and Sell Stock III
    LeetCode Binary Tree Maximum Path Sum
    LeetCode Find Peak Element
    LeetCode Maximum Product Subarray
    LeetCode Intersection of Two Linked Lists
    一天一个设计模式(1)——工厂模式
    PHP迭代器 Iterator
  • 原文地址:https://www.cnblogs.com/luxiaoming/p/5158891.html
Copyright © 2011-2022 走看看