NOIP 模拟23

时间:2021-07-25
本文章向大家介绍NOIP 模拟23,主要包括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 }
View Code

注:学习线段树的核心操作,以及转移影响的逻辑关系,注意思考问题的全面性

原文地址:https://www.cnblogs.com/HZOI-LYM/p/15059031.html