【NOI2005】维护数列

Description

维护一个数列的如下操作:

  • 在某个位置后插入一段数列
  • 在某个位置后删除一段数列
  • 将连续的一段数列修改为某个值
  • 将一段数列翻转
  • 求一段数列的和
  • 求整个数列的最大子段和

Solution

魔鬼Splay题

用Splay维护序列,以下标为权值建树。

如果插入一段序列,我们就将这段序列本身先建成一棵树,然后连到原来的树上即可

如果删除一段序列,那么直接切断子树即可

修改和翻转操作可以维护两个标记

最大子段和可以维护三个变量来实现

具体见代码

由于本题的空间限制比较严格,所以我们需要尽可能的节省空间,具体地,每次删除操作的时候,我们记录被删除的点的编号,放入一个“垃圾箱”

如果新建节点时垃圾箱不为空那么直接使用垃圾箱里的节点编号即可

时间复杂度为$O(mlogn)$

Code

  1 #include <bits/stdc++.h>
  2 namespace shl {
  3     typedef long long ll;
  4     using std :: max;
  5     const int N = 500010;
  6     const ll INF = 2147483647;
  7     inline int read() {
  8         int ret = 0, op = 1;
  9         char c = getchar();
 10         while (!isdigit(c)) {
 11             if (c == '-') op = -1; 
 12             c = getchar();
 13         }
 14         while (isdigit(c)) {
 15             ret = (ret << 3) + (ret << 1) + c - '0';
 16             c = getchar();
 17         }
 18         return ret * op;
 19     }
 20     struct Splay {
 21         int fa, ch[2], tag, rev, size;
 22         ll sum, val, lmax, rmax, maxx;
 23     } a[N];
 24     int n, m;
 25     int tot = 0, root = 0;
 26     int bin[N << 2], bintop = 0;
 27     ll in[N];
 28     char opt[15];
 29     int New(int val) {
 30         int id = bintop ? bin[bintop--] : ++tot;
 31         a[id].fa = a[id].ch[0] = a[id].ch[1] = a[id].rev = a[id].tag = 0; 
 32         a[id].size = 1; a[id].val = val;
 33         a[id].sum = a[id].maxx = val; a[id].lmax = a[id].rmax = max(val, 0);
 34         return id;
 35     }
 36     void recycle(int now) {
 37         int l = a[now].ch[0];
 38         int r = a[now].ch[1];
 39         if (l) recycle(l);
 40         if (r) recycle(r);
 41         bin[++bintop] = now;
 42     }
 43     inline void pushup(int now) {
 44         int l = a[now].ch[0], r = a[now].ch[1];
 45         a[now].size = a[l].size + a[r].size + 1;
 46         a[now].sum = a[l].sum + a[r].sum + a[now].val;
 47         a[now].lmax = max(a[l].lmax, a[l].sum + a[now].val + a[r].lmax);
 48         a[now].rmax = max(a[r].rmax, a[r].sum + a[now].val + a[l].rmax);
 49         a[now].maxx = max(max(a[l].maxx, a[r].maxx), a[l].rmax + a[now].val + a[r].lmax);
 50     }
 51     inline void pushdown(int now) {
 52         int l = a[now].ch[0], r = a[now].ch[1];
 53         if (a[now].tag) {
 54             if (l) a[l].val = a[now].val, a[l].tag = 1, a[l].sum = a[now].val * a[l].size;
 55             if (r) a[r].val = a[now].val, a[r].tag = 1, a[r].sum = a[now].val * a[r].size;
 56             if (a[now].val > 0) {
 57                 if (l) a[l].lmax = a[l].rmax = a[l].maxx = a[l].sum;
 58                 if (r) a[r].lmax = a[r].rmax = a[r].maxx = a[r].sum;
 59             }
 60             else {
 61                 if (l) a[l].lmax = a[l].rmax = 0, a[l].maxx = a[l].val;
 62                 if (r) a[r].lmax = a[r].rmax = 0, a[r].maxx = a[r].val;
 63             }
 64             a[now].tag = 0;
 65         }
 66         if (a[now].rev) {
 67             if (l) a[l].rev ^= 1, std :: swap(a[l].ch[0], a[l].ch[1]), std :: swap(a[l].lmax, a[l].rmax);
 68             if (r) a[r].rev ^= 1, std :: swap(a[r].ch[0], a[r].ch[1]), std :: swap(a[r].lmax, a[r].rmax);
 69             a[now].rev = 0;
 70         }
 71     }
 72     inline void connect(int x, int fa, int op) {
 73         a[x].fa = fa; a[fa].ch[op] = x;
 74     }
 75     inline void rotate(int x) {
 76         int y = a[x].fa;
 77         int z = a[y].fa;
 78         int xson = a[y].ch[1] == x;
 79         int yson = a[z].ch[1] == y;
 80         int B = a[x].ch[xson ^ 1];
 81         connect(B, y, xson); connect(y, x, xson ^ 1); connect(x, z, yson);
 82         pushup(y); pushup(x);
 83     }
 84     void splay(int from, int to) {
 85         while (a[from].fa != to) {
 86             int y = a[from].fa;
 87             int z = a[y].fa;
 88             if (z != to) 
 89                 (a[y].ch[0] == from) ^ (a[z].ch[0] == y) ? rotate(from) : rotate(y);
 90             rotate(from);
 91         }
 92         if (to == 0) root = from;
 93     }
 94     int build(int fa, int l, int r) {
 95         if (l > r) return 0;
 96         int mid = l + r >> 1;
 97         int now = New(in[mid]);
 98         a[now].fa = fa;
 99         a[now].ch[0] = build(now, l, mid - 1);
100         a[now].ch[1] = build(now, mid + 1, r);
101         pushup(now);
102         return now;
103     }
104     int kth(int now, int k) {
105         pushdown(now);
106         int l = a[now].ch[0];
107         int r = a[now].ch[1];
108         if (k <= a[l].size) return kth(l, k);
109         if (k == a[l].size + 1) return now;
110         return kth(r, k - a[l].size - 1);
111     }
112     void insert(int x, int num) {
113         int now = build(0, 1, num);
114         int u = kth(root, x); splay(u, 0);
115         int v = kth(root, x + 1); splay(v, u);
116         a[v].ch[0] = now;
117         a[now].fa = v;
118         pushup(v); pushup(u);
119     }
120     void del(int l, int r) {
121         int u = kth(root, l - 1); splay(u, 0);
122         int v = kth(root, r + 1); splay(v, u);
123         recycle(a[v].ch[0]); 
124         a[v].ch[0] = 0;
125         pushup(v); pushup(u);
126     }
127     void update(int l, int r, int data) {
128         int u = kth(root, l - 1); splay(u, 0); 
129         int v = kth(root, r + 1); splay(v, u);    
130         int now = a[v].ch[0];
131         a[now].val = data;
132         a[now].tag = 1;
133         a[now].sum = data * a[now].size;
134         if (data > 0) a[now].lmax = a[now].rmax = a[now].maxx = a[now].sum;
135         else a[now].lmax = a[now].rmax = 0, a[now].maxx = a[now].val;
136         pushup(v); pushup(u);        
137     }
138     void reverse(int l, int r) {
139         int u = kth(root, l - 1); splay(u, 0); 
140         int v = kth(root, r + 1); splay(v, u);    
141         int now = a[v].ch[0];
142         a[now].rev ^= 1;
143         std :: swap(a[now].ch[0], a[now].ch[1]);
144         std :: swap(a[now].lmax, a[now].rmax);
145         pushup(v); pushup(u);    
146     }
147     ll querymaxx() {
148         return a[root].maxx;
149     }
150     ll querysum(int l, int r) {
151         int u = kth(root, l - 1); splay(u, 0); 
152         int v = kth(root, r + 1); splay(v, u);
153         
154         return a[a[v].ch[0]].sum;
155     }
156     inline void init() {
157         a[0].fa = a[0].ch[0] = a[0].ch[1] = a[0].rev = a[0].tag = 0;
158         a[0].maxx = -INF;
159         a[0].sum = a[0].val = a[0].size = 0;
160         a[0].lmax = a[0].rmax = 0;
161      }
162     int main() {
163         init();
164         n = read() + 2; m = read();
165         in[1] = in[n] = -INF;
166         for (register int i = 2; i < n; ++i) in[i] = read();
167         root = build(0, 1, n);
168         while (m--) {
169             scanf("%s", opt);
170             if (opt[0] == 'M' && opt[2] == 'X') {printf("%lld\n", querymaxx()); continue ;}
171             int x = read() + 1;
172             int num = read();
173             if (opt[0] == 'I') {
174                 for (register int i = 1; i <= num; ++i) in[i] = read();
175                 insert(x, num);
176             }
177             else if (opt[0] == 'D') del(x, x + num - 1);
178             else if (opt[0] == 'M' && opt[2] == 'K') update(x, x + num - 1, read());
179             else if (opt[0] == 'R') reverse(x, x + num - 1);
180             else if (opt[0] == 'G') printf("%lld\n", querysum(x, x + num - 1));
181         }    
182         return 0;
183     }
184 };
185 int main() {
186     shl :: main();
187     return 0;
188 }
AC Code

 

posted @ 2019-08-18 16:54  AD_shl  阅读(256)  评论(0编辑  收藏  举报