NOIP 模拟23
T1:
序列操作,支持区间覆盖,区间异或,线段树解决
线段树区间操作时间复杂度的保证就是懒惰标记,可以说
懒惰标记就是线段树的核心
考虑懒惰标记的本质是记录操作所带来的影响,仅在
使用时才拓展历史上所造成的影响,以此保证时间复杂度。
于是,当存在多种影响时(多个标记),须考虑影响之间
的逻辑关系与影响,以一定的关系进行多影响的拓展。
对于本题而言,两种思路,一是直接记录最靠左0的
位置进行拓展,考虑每种操作的影响(操作3是将最左0与
最左1位置互换),发现要拓展出最左1进行辅助转移。
二是记录区间中0的个数,类似与区间求排名的方式
找到最左值即可
对于懒惰标记的下放,首先区间覆盖的优先级大于
区间异或(由标记本身的性质得出),因此,在转移3标记
时,要先考虑1,2标记的影响。
代码如下:
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef int I; 4 typedef void V; 5 typedef bool B; 6 typedef long long LL; 7 const I MAXM = 1e5 + 3; 8 I m,cnt; 9 LL auxiliary[MAXM * 3]; 10 struct QUERY { 11 I typ; 12 LL l,r; 13 }question[MAXM]; 14 inline V Discretization () { 15 for (I i(1);i <= m; ++ i) 16 auxiliary[++cnt] = question[i].l, auxiliary[++cnt] = question[i].r, auxiliary[++cnt] = question[i].r + 1; 17 sort (auxiliary + 1,auxiliary + cnt + 1); 18 cnt = unique (auxiliary + 1,auxiliary + cnt + 1) - auxiliary - 1; 19 for (I i(1);i <= m; ++ i) 20 question[i].l = lower_bound (auxiliary + 1,auxiliary + cnt + 1,question[i].l) - auxiliary, 21 question[i].r = lower_bound (auxiliary + 1,auxiliary + cnt + 1,question[i].r) - auxiliary; 22 } 23 namespace SGT { 24 #define lc(x) (x << 1) 25 #define rc(x) (x << 1 | 1) 26 #define mid (l + r >> 1) 27 #define update(x) (pos0[x] = min (pos0[lc(x)],pos0[rc(x)]),pos1[x] = min(pos1[lc(x)],pos1[rc(x)])) 28 I pos0[MAXM * 12],pos1[MAXM * 12]; 29 bool tag1[MAXM * 12],tag2[MAXM * 12],tag3[MAXM * 12]; 30 inline V pushdown (I x,I l,I r) { 31 if (tag1[x]) { 32 tag1[x] = 0; 33 pos0[lc(x)] = INT_MAX, pos1[lc(x)] = l, tag1[lc(x)] = 1, tag2[lc(x)] = tag3[lc(x)] = 0; 34 pos0[rc(x)] = INT_MAX, pos1[rc(x)] = mid + 1, tag1[rc(x)] = 1, tag2[rc(x)] = tag3[rc(x)] = 0; 35 } 36 if (tag2[x]) { 37 tag2[x] = 0; 38 pos0[lc(x)] = l, pos1[lc(x)] = INT_MAX, tag2[lc(x)] = 1, tag1[lc(x)] = tag3[lc(x)] = 0; 39 pos0[rc(x)] = mid + 1, pos1[rc(x)] = INT_MAX, tag2[rc(x)] = 1, tag1[rc(x)] = tag3[rc(x)] = 0; 40 } 41 if (tag3[x]) { 42 tag3[x] = 0; 43 swap (pos0[lc(x)],pos1[lc(x)]), tag1[lc(x)] || tag2[lc(x)] ? (swap (tag1[lc(x)],tag2[lc(x)]),1) : tag3[lc(x)] ^= 1; 44 swap (pos0[rc(x)],pos1[rc(x)]), tag1[rc(x)] || tag2[rc(x)] ? (swap (tag1[rc(x)],tag2[rc(x)]),1) : tag3[rc(x)] ^= 1; 45 } 46 } 47 V found (I x,I l,I r) { 48 pos0[x] = l, pos1[x] = INT_MAX; 49 if (l == r) return ; 50 found (lc(x),l,mid), found (rc(x),mid + 1,r); 51 } 52 V secmod1 (I x,I l,I r,I ql,I qr) { 53 if (ql <= l && r <= qr) return (V)(pos0[x] = INT_MAX, pos1[x] = l, tag1[x] = 1, tag2[x] = tag3[x] = 0); 54 pushdown (x,l,r); 55 if (ql <= mid) secmod1 (lc(x),l,mid,ql,qr); 56 if (qr > mid) secmod1 (rc(x),mid + 1,r,ql,qr); 57 update (x); 58 } 59 V secmod2 (I x,I l,I r,I ql,I qr) { 60 if (ql <= l && r <= qr) return (V)(pos0[x] = l, pos1[x] = INT_MAX, tag2[x] = 1, tag1[x] = tag3[x] = 0); 61 pushdown (x,l,r); 62 if (ql <= mid) secmod2 (lc(x),l,mid,ql,qr); 63 if (qr > mid) secmod2 (rc(x),mid + 1,r,ql,qr); 64 update (x); 65 } 66 V secmod3 (I x,I l,I r,I ql,I qr) { 67 if (ql <= l && r <= qr) return (V)(swap (pos0[x],pos1[x]), tag1[x] || tag2[x] ? (swap (tag1[x],tag2[x]),1) : tag3[x] ^= 1); 68 pushdown (x,l,r); 69 if (ql <= mid) secmod3 (lc(x),l,mid,ql,qr); 70 if (qr > mid) secmod3 (rc(x),mid + 1,r,ql,qr); 71 update (x); 72 } 73 } 74 signed main () { 75 cin >> m; 76 for (I i(1);i <= m; ++ i) 77 cin >> question[i].typ >> question[i].l >> question[i].r; 78 auxiliary[++cnt] = 1; 79 Discretization (); 80 SGT :: found (1,1,cnt); 81 for (I i(1);i <= m; ++ i) { 82 switch (question[i].typ) { 83 case 1 : SGT :: secmod1 (1,1,cnt,question[i].l,question[i].r); break; 84 case 2 : SGT :: secmod2 (1,1,cnt,question[i].l,question[i].r); break; 85 case 3 : SGT :: secmod3 (1,1,cnt,question[i].l,question[i].r); break; 86 } 87 cout << auxiliary[SGT :: pos0[1]] << endl; 88 } 89 }
注:学习线段树的核心操作,以及转移影响的逻辑关系,注意思考问题的全面性

浙公网安备 33010602011771号