POJ 3225 成段更新 并补集.cpp

题意:

  给出一些集合和原来的集合进行多种运算,输出运算后的结果..

  

输入:

  T a b 表示是原集合与该集合进行T操作~

  一开始集合为空..

  最后输出结果~如果是空集合就输出empty set

 

思路:

  这道题巧妙的地方是根据集合操作的特点把运算改成了成段的数据更新..

  

  线段树延迟标记延迟了更新的结果..

 

  根据集合操作的特点..

  可以看出:

    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互换

  其中如果该区间接受到了覆盖标记..那原来的异或标记就可以清零了..

  至于开闭区间可以通过 把每个点看成两个点..其中奇数表示该点是开区间..偶数表示该点是闭区间..

 

  两个数组..XOR--异或标记..COVER--覆盖标记..

 

  FXOR:

    
    当一个节点得到异或标记的时候,先判断覆盖标记,如果是0或1,直接改变一下覆盖标记,不然的话改变异或标记

  pushDown:

    当一个节点得到覆盖标记时把异或标记清空

    向下更新的时候根据覆盖标记和异或标记进行更新.. 

    记得更新完节点后该点要归为原始状态..

  modify:

    先找到范围..然后根据运算特点对区间内的数进行更新..

    更新完之后就可以返回了~

    如果没在范围内~就先向下更新节点~然后进行判断更新..

  query:

    找到对应的范围然后进行标记..

 

Tips:

    各种更新各种细节吖~要好好理解然后再做~

    

Code:

View Code
  1 #include <stdio.h>
  2 #include <cstring>
  3 #include <iostream>
  4 using namespace std;
  5 
  6 const int MAXN = 131072;
  7 int cover[MAXN<<2], XOR[MAXN<<2];
  8 bool vis[MAXN+1];
  9 
 10 void FXOR(int rt)
 11 {
 12     if(cover[rt] != -1) cover[rt] ^= 1;
 13     else XOR[rt] ^= 1;
 14 }
 15 
 16 void pushDown(int rt) {
 17     if(cover[rt] != -1) {
 18         cover[rt<<1] = cover[rt<<1|1] = cover[rt];
 19         cover[rt] = -1;
 20         XOR[rt<<1] = XOR[rt<<1|1] = 0;///!!!
 21     }
 22     if(XOR[rt]) {
 23         FXOR(rt<<1);
 24         FXOR(rt<<1|1);
 25         XOR[rt] = 0;
 26     }
 27 }
 28 
 29 void modify(char opt, int l, int r, int L, int R, int rt) {
 30     if(l <= L && r >= R) {
 31         if(opt == 'U') {
 32             cover[rt] = 1;
 33             XOR[rt] = 0;
 34         }
 35         else if(opt == 'D'){
 36             cover[rt] = 0;
 37             XOR[rt] = 0;///!!!
 38         }
 39         else if(opt == 'C' || opt == 'S')
 40             FXOR(rt);
 41         return;
 42     }
 43     //if(l == r) return;
 44     pushDown(rt);
 45     int mid = (L+R)>>1;
 46     if(l <= mid) modify(opt, l, r, L, mid, rt<<1);
 47     else if(opt == 'I' || opt == 'C')
 48         cover[rt<<1] = XOR[rt<<1] = 0;///!!!
 49     if(r > mid) modify(opt, l, r, mid+1, R, rt<<1|1);
 50     else if(opt == 'I' || opt == 'C')
 51         cover[rt<<1|1] = XOR[rt<<1|1] = 0;///!!!
 52 }
 53 
 54 void query(int l, int r, int rt) {
 55         if(cover[rt] == 1) {
 56             for(int i = l; i <= r; ++i)
 57                 vis[i] = 1;
 58             return;//!!!
 59         }
 60         else if(cover[rt] == 0) return;
 61     if(l == r) return;
 62     pushDown(rt);
 63     int mid = (l+r)>>1;
 64     query(l, mid, rt<<1);
 65     query(mid+1, r, rt<<1|1);
 66 }
 67 
 68 int main()
 69 {
 70     int i, j, k;
 71     char opt, c, cc;
 72     int a, b;
 73     int st = -1, en;
 74     bool flag = false;
 75     while(scanf("%c %c %d,%d %c", &opt, &c, &a, &b, &cc) != EOF) {
 76         getchar();
 77         a *= 2, b *= 2;
 78         if(c == '(') a++;
 79         if(cc == ')') b--;
 80         if(a > b) {
 81             if(opt == 'I' || opt == 'C')
 82             cover[1] = XOR[1] = 0;
 83         } else modify(opt, a, b, 0, MAXN, 1);
 84     }
 85     query(0, MAXN, 1);
 86     for(i = 0; i <= MAXN; ++i) {///!!!
 87         if(vis[i]) {
 88             if(st == -1) st = i;
 89             en = i;
 90         } else if(vis[i] == 0 && st != -1) {
 91             if(flag) printf(" ");
 92             printf("%c%d,%d%c", st%2?'(':'[', (st)/2, (en+1)/2, en%2?')':']');
 93             flag = true;
 94             st = -1;//!!!
 95         }
 96     }
 97     if(!flag) printf("empty set");
 98     puts("");
 99     return 0;
100 }

题目链接:http://poj.org/problem?id=3225

原文地址:https://www.cnblogs.com/Griselda/p/2743935.html