zoukankan      html  css  js  c++  java
  • POJ 3225 线段树区间更新(两种更新方式)

    http://blog.csdn.net/niuox/article/details/9664487

    这道题明显是线段树,根据题意可以知道:

    (用0和1表示是否包含区间,-1表示该区间内既有包含又有不包含)

    U:把区间[l,r]覆盖成1

    I:把[-∞,l)(r,∞]覆盖成0

    D:把区间[l,r]覆盖成0

    C:把[-∞,l)(r,∞]覆盖成0 , 且[l,r]区间0/1互换

    S:[l,r]区间0/1互换

    这里有两个地方和区间更新不一样

    一个是会更新选中区间以外的所有区域,可以这样子解决:

    void update(char val,int L,int R,int l,int r,int rt)
    {
        ...
        int mid = (l + r)>>1;
        if (L <= mid)
        {
            update(val,L,R,l,mid,rt<<1);
        }
        else if(val == 'I' || val == 'C')
        {
            a[rt<<1] = col[rt<<1] = 0;
        }
        if(R > mid)
        {
            update(val,L,R,mid+1,r,rt<<1|1);
        }
        else if(val == 'I' || val == 'C')
        {
            a[rt<<1|1] = col[rt<<1|1] = 0;
        }
    }

    if判断左边是否小于mid,如果不是,那么更新它的左边就是我们想要的选中区域外了,右边同理。

    第二个是有两种更新方式,覆盖和异或

    这种问题一般需要两种标记,但这里其中一种是覆盖,所以一种标记可以用值自身表示,-1表示杂,非-1表示纯。一个标记数组就行。

    然后还要理清两种标记使用的方式

    很明显我们可以知道这个性质:

    当一个区间被覆盖后,不管之前有没有异或标记都没有意义了
    所以当一个节点得到覆盖标记时把异或标记清空

    第三种是开闭区间,这里可以通过把所有数乘2处理(偶数表示端点,奇数表示两端点间的区间)。

    #include <iostream>
    #include <string>
    #include <cstring>
    #include <cstdlib>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #include <stack>
    #include <queue>
    #include <cctype>
    #include <vector>
    #include <iterator>
    #include <set>
    #include <map>
    #include <sstream>
    using namespace std;
    
    #define mem(a,b) memset(a,b,sizeof(a))
    #define pf printf
    #define sf scanf
    #define spf sprintf
    #define pb push_back
    #define debug printf("!
    ")
    #define MAXN 65535*2
    #define MAX(a,b) a>b?a:b
    #define blank pf("
    ")
    #define LL long long
    #define ALL(x) x.begin(),x.end()
    #define INS(x) inserter(x,x.begin())
    #define pqueue priority_queue
    #define INF 0x3f3f3f3f
    
    int n,m;
    
    int a[MAXN<<4],col[MAXN<<4],ans;
    
    bool vis[MAXN];
    
    void FXOR(int x)
    {
        if(a[x]!=-1) a[x]^=1;
        else col[x]^=1;
    }
    
    
    void PushDown(int rt)
    {
        if(a[rt] != -1)
        {
            a[rt<<1] = a[rt<<1|1] = a[rt];
            col[rt<<1] = col[rt<<1|1] = 0;
            a[rt] = -1;
        }
        if(col[rt])
        {
            FXOR(rt<<1);
            FXOR(rt<<1|1);
            col[rt] = 0;
        }
    }
    
    void update(char val,int L,int R,int l,int r,int rt)
    {
        if(L <= l && r <= R)
        {
            if(val == 'U')
            {
                a[rt] = 1;
                col[rt] = 0;
            }
            else if(val == 'D')
            {
                a[rt] = col[rt] = 0;
            }
            else if(val == 'C' || val == 'S')
            {
                FXOR(rt);
            }
            return;
        }
        PushDown(rt);
        int mid = (l + r)>>1;
        if (L <= mid)
        {
            update(val,L,R,l,mid,rt<<1);
        }
        else if(val == 'I' || val == 'C')
        {
            a[rt<<1] = col[rt<<1] = 0;
        }
        if(R > mid)
        {
            update(val,L,R,mid+1,r,rt<<1|1);
        }
        else if(val == 'I' || val == 'C')
        {
            a[rt<<1|1] = col[rt<<1|1] = 0;
        }
    }
    
    void query(int l,int r,int rt)
    {
        if(a[rt] == 1)
        {
            for(int i = l;i<=r;i++) vis[i] = true;
            return;
        }
        else if(a[rt] == 0) return;
        if(l == r) return;
        PushDown(rt);
        int mid = (l + r)>>1;
        query(l,mid,rt<<1);
        query(mid+1,r,rt<<1|1);
    }
    
    
    int main()
    {
        int r,t;
        char op,lchar,rchar;
        a[1] = col[1] = 0;
        while(~sf("%c %c%d,%d%c
    ",&op,&lchar,&r,&t,&rchar))
        {
            r<<=1;
            t<<=1;
            if(lchar == '(') r++;
            if(rchar == ')') t--;
            update(op,r,t,0,MAXN,1);
        }
        query(0,MAXN,1);
        int s = -1,e;
        bool flag = false;
        for(int i=0;i<=MAXN;i++)
        {
            if(vis[i])
            {
                if(s == -1) s = i;
                e = i;
            }
            else
            {
                if(s!=-1)
                {
                    if(flag) pf(" ");
                    pf("%c%d,%d%c",s&1?'(':'[',s>>1,(e+1)>>1,e&1?')':']');
                    s = -1;
                    flag = true;
                }
            }
        }
        if(!flag) printf("empty set");
        return 0;
    
    }
  • 相关阅读:
    前端与算法 leetcode 344. 反转字符串
    JavaScript闭包使用姿势指南
    前端与算法 leetcode 48. 旋转图像
    前端与算法 leetcode 36. 有效的数独
    前端与算法 leetcode 1. 两数之和
    前端与算法 leetcode 283. 移动零
    前端与编译原理 用js去运行js代码 js2run
    前端与算法 leetcode 66. 加一
    前端与算法 leetcode 350. 两个数组的交集 II
    前端与算法 leetcode 26. 删除排序数组中的重复项
  • 原文地址:https://www.cnblogs.com/qlky/p/5737676.html
Copyright © 2011-2022 走看看