做了好多线段树,顿时感觉线段树博大精深,虽然最基本的只是递归的更新,但是在写线段树的时候需要注意的地方真是太多太多,每个题都有自己要注意的地方,每个题都有自己的解决问题的小技巧,因而做线段树的时候需要自己对于线段树有特定的分析和不同的做法,好了感慨完了开始说题。
本题说的是对一排数进行操作,主要有四个
Operation | Notation | Definition |
---|---|---|
Union | A ∪ B | {x : x ∈ A or x ∈ B} |
Intersection | A ∩ B | {x : x ∈ A and x ∈ B} |
Relative complementation | A − B | {x : x ∈ A but x ∉ B} |
Symmetric difference | A ⊕ B | (A − B) ∪ (B − A) |
Command | Semantics |
---|---|
U T | S ← S ∪ T |
I T | S ← S ∩ T |
D T | S ← S − T |
C T | S ← T − S |
S T | S ← S ⊕ T |
以输入为例:
U [1,5]
D [3,3]
S [2,4]
C (1,5)
I (2,3]
一开始对空集区并得到[1,5];然后集合与[3,3]做差得到[1,3)和(3,5],以此类推直到得到最终结果(2,3)
这道题要注意的地方其实还是不少的首先是对于开括号和闭括号的操作,如何分别开括号和闭括号,解决方法是对每个数乘以二,这样整点数字用他的两倍来表示,两个数倍增之后中间的奇数则表示两个数之间的小数,比如2,3分别用电4,6来表示,而5则会表示(2,3)表示的数字。
另一个需要注意的地方也就是线段树的更新,这个如果做的线段树比较多的话也不算是新知识,就是如何使用pushdown();
在使用pushdown()的时候需要把父节点的cover设置为-1而不是0或者1;
void pushdown(int o) { if(cover[o] != -1) { cover[o << 1] = cover[o << 1 | 1] = cover[o]; XO[o << 1] = XO[o << 1 | 1] = 0; cover[o] = -1; } if(XO[o]) { FOX(o << 1); FOX(o << 1 | 1); XO[o] = 0; } }
这个还要靠以后多做题,培养意识。
<pre name="code" class="cpp">#include <iostream> #include <cstring> #include <cstdlib> #include <cmath> #include <vector> #include <functional> #include <cstdio> #include <queue> #include <map> #include <algorithm> #include <stack> #include <utility> typedef long long ll; using namespace std; const int mx = 131072; int cover[mx << 2],XO[mx << 2]; int numl[mx],numr[mx]; int qr,ql,cnt; char a; bool has[mx]; void FOX (int o) { if(cover[o] != -1)cover[o] ^= 1; else XO[o] ^= 1; } void pushdown(int o) { if(cover[o] != -1) { cover[o << 1] = cover[o << 1 | 1] = cover[o]; XO[o << 1] = XO[o << 1 | 1] = 0; cover[o] = -1; } if(XO[o]) { FOX(o << 1); FOX(o << 1 | 1); XO[o] = 0; } } //void pushup(int o) //{ // if(cover[o << 1] == 1&& cover[o << 1|1] == 1) // cover[o] = 1; // if(cover[o << 1] == 0&& cover[o << 1|1] == 0) // cover[o] = 0; //} void update(int o = 1,int L = 0,int R = mx - 1) { if(ql <= L&&qr >= R) { if(a == 'U') { cover[o] = 1; XO[o] = 0; } if(a == 'D') { cover[o] = 0; XO[o] = 0; } if(a == 'C'|| a == 'S') FOX(o); // printf("o = %d L = %d R = %d cover = %d XO = %d\n",o,L,R,cover[o],XO[o]); return; } pushdown(o); int mid = (R + L) >> 1; if(ql <= mid) update (o << 1,L,mid); else { if(a == 'I' || a == 'C') { cover[o << 1] = 0; XO [o << 1] = 0; } } if(qr > mid) update(o << 1 | 1,mid + 1,R); else { if(a == 'I' ||a == 'C') { cover[o << 1 | 1] = 0; XO [o << 1 | 1] = 0; } } // printf("o = %d L = %d R = %d cover = %d XO = %d\n",o,L,R,cover[o],XO[o]); } void qu(int o = 1,int L = 0,int R = mx - 1) { if(cover[o] == 1) { for(int i = L; i <= R; i++) has[i] = true; return; } if(cover[o] == 0) return; if(R == L) return; pushdown(o); int mid = (R + L) >> 1; qu(o << 1,L,mid); qu(o << 1| 1,mid + 1,R); } int main () { char b,c,d; cover[1] = XO[1] = 0; while (~scanf("%c %c%d,%d%c",&a,&b,&ql,&qr,&c)) { getchar(); ql <<= 1; qr <<= 1; if(b == '(') ql++; if(c == ')') qr--; if(ql > qr) { if(a == 'C' || a == 'I') cover[1] = XO[1] = 0; continue; } update(); } int l,r,i,k,j; cnt = 0; qu(); bool flag = false; int s = -1 , e; for (int i = 0 ; i <= mx ; i ++) { if (has[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; }