zoukankan      html  css  js  c++  java
  • POJ 3225 Help with Intervals --线段树区间操作

    题意:给你一些区间操作,让你输出最后得出的区间。

    解法:区间操作的经典题,借鉴了网上的倍增算法,每次将区间乘以2,然后根据区间开闭情况做微调,这样可以有效处理开闭区间问题。

    线段树维护两个值: cov 和 rev  ,一个是覆盖标记,0表示此区间被0覆盖,1表示被1覆盖,-1表示未被覆盖, rev为反转标记,rev = 1表示反转,0表示不翻转

    所以集合操作可以化为如下区间操作:

    U l r:   把区间[l,r]覆盖成1
    I  l r:   把[0,l)(r,MAX]覆盖成0
    D l r:   把区间[l,r]覆盖成0
    C l r:   把[0,l)(r,MAX]覆盖成0 , 且[l,r]区间0/1互换
    S l r:   [l,r]区间0/1互换

    重点在于pushdown函数以及边界处理。

    代码:

    #include <iostream>
    #include <cmath>
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    #define N (65536*2)
    
    struct Tree
    {
        int cov,rev;   //cov -1  rev 0
    }tree[4*N];
    
    struct ANS
    {
        char L,R;
        int A,B;
    }ans[N+1];
    int cnt;
    
    void build(int l,int r,int rt)
    {
        tree[rt].cov = 0;
        tree[rt].rev = 0;
        if(l == r) return;
        int mid = (l+r)/2;
        build(l,mid,2*rt);
        build(mid+1,r,2*rt+1);
    }
    
    void pushdown(int l,int r,int rt)
    {
        if(tree[rt].cov != -1)
        {
            tree[2*rt].cov = tree[2*rt+1].cov = tree[rt].cov;
            tree[2*rt].rev = tree[2*rt+1].rev = 0;
            tree[rt].cov = -1;
        }
        if(tree[rt].rev)
        {
            if(tree[2*rt].cov != -1)
                tree[2*rt].cov ^= 1;
            else
                tree[2*rt].rev ^= 1;
    
            if(tree[2*rt+1].cov != -1)
                tree[2*rt+1].cov ^= 1;
            else
                tree[2*rt+1].rev ^= 1;
            tree[rt].rev = 0;
        }
    }
    
    void update(int l,int r,int aa,int bb,int op,int rt)
    {
        if(aa > bb || aa < 0) return;    //必须要加,否则会RE
        if(aa <= l && bb >= r)
        {
            if(op != 2)   //cover to 0/1
            {
                tree[rt].cov = op;
                tree[rt].rev = 0;
            }
            else          //op == 2  reverse
            {
                if(tree[rt].cov != -1)
                    tree[rt].cov ^= 1;
                else
                    tree[rt].rev ^= 1;
            }
            return;
        }
        pushdown(l,r,rt);
        int mid = (l+r)/2;
        if(aa <= mid)
            update(l,mid,aa,bb,op,2*rt);
        if(bb > mid)
            update(mid+1,r,aa,bb,op,2*rt+1);
    }
    
    void query(int l,int r,int rt)
    {
        if(tree[rt].cov == 1)
        {
            ans[cnt].L = (l%2==1)?'(':'[';
            ans[cnt].A = l/2;
            ans[cnt].R = (r%2==1)?')':']';
            ans[cnt].B = (r+1)/2;
            cnt++;
        }
        else if(tree[rt].cov == 0) return;
        else
        {
            pushdown(l,r,rt);
            int mid = (l+r)/2;
            query(l,mid,2*rt);
            query(mid+1,r,2*rt+1);
        }
    }
    
    void print()
    {
        char nowl,nowr;
        int nowA,nowB;
        if(cnt == 0)
            puts("empty set");
        else
        {
            nowl = ans[0].L;
            nowr = ans[0].R;
            nowA = ans[0].A;
            nowB = ans[0].B;
            for(int i=1;i<cnt;i++)
            {
                if(ans[i].A == nowB && (nowr == ']' || ans[i].L == '['))
                {
                    nowB = ans[i].B;
                    nowr = ans[i].R;
                }
                else
                {
                    printf("%c%d,%d%c ",nowl,nowA,nowB,nowr);
                    nowl = ans[i].L;
                    nowr = ans[i].R;
                    nowA = ans[i].A;
                    nowB = ans[i].B;
                }
            }
            printf("%c%d,%d%c
    ",nowl,nowA,nowB,nowr);
        }
    }
    
    int main()
    {
        int a,b;
        char L,R,op;
        int n = 65536*2;
        build(0,n,1);
        while(scanf("%c %c%d,%d%c
    ",&op,&L,&a,&b,&R)!=EOF) // '
    ' 务必要加
        {
            a = 2*a; if(L == '(') a++;
            b = 2*b; if(R == ')') b--;
            if(a > b || a < 0) continue;
            if(op == 'U')  //并集
                update(0,n,a,b,1,1);
            else if(op == 'I')
            {
                update(0,n,0,a-1,0,1);
                update(0,n,b+1,n,0,1);
            }
            else if(op == 'D')
                update(0,n,a,b,0,1);
            else if(op == 'C')
            {
                update(0,n,0,a-1,0,1);
                update(0,n,b+1,n,0,1);
                update(0,n,a,b,2,1);
            }
            else
                update(0,n,a,b,2,1);
        }
        cnt = 0;
        query(0,n,1);
        print();
        return 0;
    }
    View Code

    参考文章: http://my.oschina.net/llmm/blog/124256

  • 相关阅读:
    poj 2002 Squares 几何二分 || 哈希
    hdu 1969 Pie
    hdu 4004 The Frog's Games 二分
    hdu 4190 Distributing Ballot Boxes 二分
    hdu 2141 Can you find it? 二分
    Codeforces Round #259 (Div. 2)
    并查集
    bfs
    二维树状数组
    一维树状数组
  • 原文地址:https://www.cnblogs.com/whatbeg/p/3941658.html
Copyright © 2011-2022 走看看