POJ 3225
基本参考http://blog.csdn.net/metalseed/article/details/8039326
总的来说,敲完一遍理解会更加好一点,标记下传法。
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互换
利用异或值来决定是否要翻转,注意标记下传时,孩子结点的值是否要翻转是根据父结点决定的。由于最新的状态是在最上层完成的,所以后代结点翻转状态基本没有,除了当父结点覆盖状态为-1(此时区间内部分子区间值为1),需要结合父结点来决定当前的异或值。
#include <cstdio> #include <cstring> #include <cctype> #include <iostream> #include <algorithm> using namespace std; const int maxn = 131072; bool hash[maxn+1]; int cover[maxn<<2]; int XOR[maxn<<2]; void PushXOR(int rt){ if(cover[rt]!=-1) cover[rt]^=1; else XOR[rt]^=1; } void PushDown(int rt){ if(cover[rt]!=-1){ cover[rt<<1]=cover[rt<<1|1]=cover[rt]; XOR[rt<<1]=XOR[rt<<1|1]=0; cover[rt]=-1; } if(XOR[rt]){ PushXOR(rt<<1); PushXOR(rt<<1|1); XOR[rt]=0; } } void update(char op,int L,int R,int l,int r,int rt){ if(L<=l&&r<=R){ if(op=='U'){ cover[rt]=1; XOR[rt]=0; } else if(op=='D'){ cover[rt]=0; XOR[rt]=0; } else if(op=='C'||op=='S'){ PushXOR(rt); } return ; } PushDown(rt); int m=(l+r)>>1; if(L<=m) update(op,L,R,l,m,rt<<1); else if(op=='I'||op=='C'){ cover[rt<<1]=XOR[rt<<1]=0; } if(m<R) update(op,L,R,m+1,r,rt<<1|1); else if(op=='I'||op=='C'){ cover[rt<<1|1]=XOR[rt<<1|1]=0; } } void query(int l,int r,int rt){ if(cover[rt]!=-1){ if(cover[rt]>0){ for(int i=l;i<=r;i++) hash[i]=true; } return ; } if(l==r) return ; PushDown(rt); int m=(l+r)>>1; query(l,m,rt<<1); query(m+1,r,rt<<1|1); } int main(){ cover[1] = XOR[1] = 0; char op , l , r; int a , b; // int tt=0; while (scanf("%c %c%d,%d%c",&op , &l , &a , &b , &r)!=EOF) { getchar(); // tt++; a <<= 1 , b <<= 1; if (l == '(') a ++; if (r == ')') b --; if (a > b) { if (op == 'C' || op == 'I') { cover[1] = XOR[1] = 0; } } else update(op , a , b , 0 , maxn , 1); // if(tt==5) break; } memset(hash,false,sizeof(hash)); 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"); puts(""); return 0; }