zoukankan      html  css  js  c++  java
  • POJ 3225 区间(带标记的线段树区间操作)

    思路:

    1. 因为要对一个区间进行多种操作,特别是相补差和对称差的情况下,要对一个区间操作怎么办?

    2. 区间的seg[] = 0, 1, -1,分别表示区间为空,有数据,两者兼有。lab[] = 0, 1 表示区间是否被标记,当seg[] = -1时才会有效(即不确定时)

    3. 对区间的5中操作,其实标记主要是为了应对于取反的操作。也算是延迟的一种方式吧,大区间取反,虽然其中可能有0,1,-1,但是最终只是针对0,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互换

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    
    #define lhs l, m, rt << 1
    #define rhs m + 1, r, rt << 1 | 1
    
    const int maxn = 131100;
    bool hash[maxn];
    int seg[maxn << 2];
    int lab[maxn << 2];
    
    void DoXor(int rt)
    {
        if (seg[rt] != -1)
            seg[rt] = seg[rt] ^ 1;
        else
            lab[rt] = lab[rt] ^ 1;
    }
    
    void PushDown(int rt)
    {
        if (seg[rt] != -1)
        {
            seg[rt << 1] = seg[rt << 1 | 1] = seg[rt];
            lab[rt << 1] = lab[rt << 1 | 1] = 0;
            seg[rt] = -1;
        }
        if (lab[rt])
        {
            DoXor(rt << 1);
            DoXor(rt << 1 | 1);
            lab[rt] = 0;
        }
    }
    
    void Update(char op, int beg, int end, int l, int r, int rt)
    {
        if (beg <= l && r <= end)
        {
            if (op == 'U')
                seg[rt] = 1, lab[rt] = 0;
            else if (op == 'D')
                seg[rt] = 0, lab[rt] = 0;
            else if (op == 'C' || op == 'S')
                DoXor(rt);
        } 
        else
        {
            PushDown(rt);
            int m = (l + r) >> 1;
    
            if (beg <= m)
                Update(op, beg, end, lhs);
            else if (op == 'I' || op == 'C')
                seg[rt << 1] = lab[rt << 1] = 0;
    
            if (end > m)
                Update(op, beg, end, rhs);
            else if (op == 'I' || op == 'C')
                seg[rt << 1 | 1] = lab[rt << 1 | 1] = 0;
        }
    }
    
    void Query(int l, int r, int rt)
    {
        if (seg[rt] == 1)
        {
            for (int i = l; i <= r; ++i)
                hash[i] = true;
            return ;
        }
        else if (seg[rt] == 0 || l == r)
            return ;
    
        PushDown(rt);
    
        int m = (l + r) >> 1;
        Query(lhs); Query(rhs);
    }
    
    int main()
    {
        seg[1] = lab[1] = 0;
    
        char op, l, r;
        int a, b;
        while (scanf("%c %c%d,%d%c\n", &op, &l, &a, &b, &r) != EOF)
        {
            a <<= 1, b <<= 1;
            if (l == '(')
                ++a;
            if (r == ')')
                --b;
    
            if (a > b)
            {
                if (op == 'C' || op == 'I')
                    seg[1] = lab[1] = 0;
            }
            else
                Update(op, a, b, 0, maxn, 1);
        }
    
        Query(0, maxn, 1);
    
        bool flag = false;
        int s = -1, e;
    
        for (int i = 0; i < maxn; ++i) 
        {
            if (hash[i])
            {
                if (s == -1) s = i;
                e = i;
            } 
            else 
            {
                if (s != -1) 
                {
                    if (flag) printf(" ");
                    flag = true;
                    printf("%c%d,%d%c",s&1?'(':'[' , s>>1 , (e+1)>>1 , e&1?')':']');
                    s = -1;
                }
            }
        }
        if (!flag) printf("empty set");
        printf("\n");
        return 0;
    }
  • 相关阅读:
    swt 更新主UI线程
    java中 快捷键输入System.out.println();
    原型设计工具
    JAVA笔记
    转:java读取配置文件的几种方法
    Server Message Block
    安全标识符
    BitLocker:如何启用网络解锁
    imageX.exe
    组策略首选项
  • 原文地址:https://www.cnblogs.com/kedebug/p/2867110.html
Copyright © 2011-2022 走看看