zoukankan      html  css  js  c++  java
  • PKU 3225 Help with Intervals

    线段树经典入门题目;

    这道题有几点不同的地方:

    1. 维护的是集合,一个点或者一段区间都是一个集合,(2,3) 是一个集合,不能简单的用线段代替集合;

    2. 用离散的 01 值表示集合,对集合的运算需要转化为 01 区间的异或与赋值操作;

    3. 01 区间上进行异或和赋值,在 pushdown 的时候只能存在一个信息,一个线段要么被赋值,要么异或,不能既被赋值,同时进行异或(cover[]和xor[]不能同时有效);

    4. 结果要求输出运算结果(集合),在查询时,要做的不是查询到左端点、右端点,而是把被赋值的区间全部标记下来(O(n)),然后一次扫描完成输出,这道题卡了很长时间就是这里没想清楚(既然用了线段树,为什么还要O(n)呢?其实是只需要一次O(n),何必用线段树呢?);

    # include <stdio.h>
    # include <string.h>
    
    # define ls ((r)<<1)
    # define rs ((r)<<1 | 1)
    # define mid (((x)+(y))>>1)
    
    # define maxn (65535 * 2)
    
    char cc[maxn << 2], xx[maxn << 2],  hh[maxn+1];
    /*************************************************************/
    void XOR(int r)
    {
        if (cc[r] != -1) cc[r] ^= 1;
        else xx[r] ^= 1;
    }
    
    void pushdown(int x, int y, int r)
    {
        /* after pushdown cc[r]==-1 && xx[r]==0 */
        if (cc[r] != -1)
        {
            cc[ls] = cc[rs] = cc[r];
            xx[ls] = xx[rs] = 0;
            cc[r] = -1;
        }
        if (xx[r])
        {
            XOR(ls);
            XOR(rs);
            xx[r] = 0;
        }
    }
    
    void cover(int x, int y, int r, int s, int t, int val)
    {
        if (s<=x && y<=t)
        {
            cc[r] = val;
            xx[r] = 0;
            return ;
        }
        pushdown(x, y, r);
        if (s <= mid) cover(x, mid, ls, s, t, val);
        if (mid+1<=t) cover(mid+1, y, rs, s, t, val);
    }
    
    void xxor(int x, int y, int r, int s, int t)
    {
        if (s<=x && y<=t)
        {
            XOR(r);
            return ;
        }
        pushdown(x, y, r);
        if (s <= mid) xxor(x, mid, ls, s, t);
        if (mid+1<=t) xxor(mid+1, y, rs, s, t);
    }
    
    void query(int x, int y, int r)
    {
        int i;
        if (cc[r]!= -1)
        {
            if (cc[r] == 1) for (i = x; i <= y; ++i) hh[i] = 1;
            return ;
        }
        // if (x == y) return ;
        pushdown(x, y, r);
        query(x, mid, ls);
        query(mid+1, y, rs);
    }
    
    /*************************************************************/
    int main()
    {
        freopen("data.in", "r", stdin);
        freopen("data.out", "w", stdout);
        
        int s, t, i, first = 1;
        char op, lp, rp;
        
        while (~scanf("%c %c%d,%d%c\n", &op, &lp, &s, &t, &rp))
        {
            s <<= 1, t <<= 1;
            if (lp == '(') ++s;
            if (rp == ')') --t;
            if (s > t || (s==t && (s&0x1)))
            {
                if (op == 'I' || op == 'C') cc[1] = 0, xx[1] = 0;
                continue;
            }
            switch(op)
            {
                case 'U': cover(0, maxn, 1, s, t, 1);break;
                case 'D': cover(0, maxn, 1, s, t, 0);break;
                case 'I': {
                              if (s>0)       cover(0, maxn, 1, 0, s-1, 0);
                              if (t<maxn) cover(0, maxn, 1, t+1, maxn, 0);
                              break;
                          }
                 case 'C': {
                              if (s>0)    cover(0, maxn, 1, 0, s-1, 0);
                              if (t<maxn) cover(0, maxn, 1, t+1, maxn, 0);
                              xxor(0, maxn, 1, s, t);
                              break;
                          }          
                 case 'S': xxor(0, maxn, 1, s, t);break;
            }
        }
        query(0, maxn, 1);
        for (i = 0; i <= maxn; ++i)
        {
            if (hh[i])
            {
                if (first) first = 0;
                else putchar(' ');
                printf("%c%d,", i&0x1 ? '(':'[', i>>1);
                while (hh[i]) ++i;
                printf("%d%c", i>>1, (i-1)&0x1 ? ')':']');
            }
        }
        if (first) puts("empty set");
        else putchar('\n');
        
        return 0;
    } 

    代码写的丑,但是刚好跑到了notonlysuccess的前面,谢谢他的线段树专辑

  • 相关阅读:
    记一道乘法&加法线段树(模版题)
    2021CCPC网络赛(重赛)题解
    Codeforces Round #747 (Div. 2)题解
    F. Mattress Run 题解
    Codeforces Round #744 (Div. 3) G题题解
    AtCoder Beginner Contest 220部分题(G,H)题解
    Educational Codeforces Round 114 (Rated for Div. 2)题解
    Codeforces Global Round 16题解
    Educational Codeforces Round 113 (Rated for Div. 2)题解
    AtCoder Beginner Contest 182 F
  • 原文地址:https://www.cnblogs.com/JMDWQ/p/2651516.html
Copyright © 2011-2022 走看看