BZOJ 1500 维修数列

维修数列

【问题描述】

【输入格式】

输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目。
第2行包含N个数字,描述初始时的数列。
以下M行,每行一条命令,格式参见问题描述中的表格。
任何时刻数列中最多含有500 000个数,数列中任何一个数字均在[-1 000, 1 000]内。
插入的数字总数不超过4 000 000个,输入文件大小不超过20MBytes。

【输出格式】

对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行。

【样例输入】

9 8
2 -6 3 5 1 -5 -3 6 3
GET-SUM 5 4
MAX-SUM
INSERT 8 3 -5 7 2
DELETE 12 1
MAKE-SAME 3 3 2
REVERSE 3 6
GET-SUM 5 4
MAX-SUM

【样例输出】

-1
10
1
10

【数据范围】

 


题解:

每一个操作都差不多是将通过将左右区间(开区间)端点转到根和右孩子

就能将整个区间转移到根的右孩子的左孩子的子树,就能直接取出信息了

  1 #include<cmath>
  2 #include<cstdio>
  3 #include<cstdlib>
  4 #include<cstring>
  5 #include<iostream>
  6 #include<algorithm>
  7 using namespace std;
  8 const int maxn = 1e6;
  9 const int inf = 2e9;
 10 inline void Scan(int &x)
 11 {
 12     char c;
 13     bool o = false;
 14     while(!isdigit(c = getchar())) o = (c != '-') ? o : true;
 15     x = c - '0';
 16     while(isdigit(c = getchar())) x = x * 10 + c - '0';
 17     if(o) x = -x;
 18 }
 19 int n, m;
 20 int num;
 21 int root;
 22 int deln;
 23 int del[maxn];
 24 int id[maxn], pri[maxn];
 25 int lc[maxn], rc[maxn], fat[maxn];
 26 int si[maxn], sum[maxn], val[maxn], lmax[maxn], rmax[maxn], kmax[maxn];
 27 int sam[maxn];
 28 bool rev[maxn];
 29 inline void Update(int x)
 30 {
 31     int l = lc[x], r = rc[x];
 32     si[x] = si[l] + si[r] + 1;
 33     sum[x] = sum[l] + sum[r] + val[x];
 34     lmax[x] = max(lmax[l], sum[l] + val[x] + max(lmax[r], 0));
 35     rmax[x] = max(rmax[r], sum[r] + val[x] + max(rmax[l], 0));
 36     kmax[x] = max(kmax[l], kmax[r]);
 37     kmax[x] = max(kmax[x], rmax[l] + lmax[r] + val[x]);
 38     kmax[x] = max(kmax[x], max(max(rmax[l], lmax[r]), 0) + val[x]);
 39 }
 40 inline void Change(int x, int c)
 41 {
 42     sam[x] = val[x] = c;
 43     sum[x] = si[x] * c;
 44     kmax[x] = lmax[x] = rmax[x] = c > 0 ? sum[x] : c;
 45 }
 46 inline void Rever(int x)
 47 {
 48     rev[x] ^= 1;
 49     swap(lmax[x], rmax[x]);
 50     swap(lc[x], rc[x]);
 51 }
 52 inline void Down(int x)
 53 {
 54     int l = lc[x], r = rc[x];
 55     if(rev[x])
 56     {
 57         Rever(l), Rever(r);
 58         rev[x] = 0;
 59     }
 60     if(sam[x] != inf)
 61     {
 62         Change(l, sam[x]), Change(r, sam[x]);
 63         sam[x] = inf;
 64     }
 65 }
 66 inline void Printtree(int k)
 67 {
 68     if(!k) return;
 69     Down(k);
 70     printf("k=%d v=%d lc=%d rc=%d si=%d sum=%d\n", k, val[k], lc[k], rc[k], si[k], sum[k]);
 71     Printtree(lc[k]);
 72     Printtree(rc[k]);
 73 }
 74 void Print(int k)
 75 {
 76     if(!k) return;
 77     Down(k);
 78     Print(lc[k]);
 79     printf("%d ", val[k]);
 80     Print(rc[k]);
 81 }
 82 inline void Turn(int x)
 83 {
 84     int y = fat[x], z = fat[y];
 85     int w = (lc[y] != x) ? lc[x] : rc[x];
 86     Down(y), Down(x);
 87     fat[y] = x;
 88     fat[x] = z;
 89     if(w) fat[w] = y;
 90     if(z)
 91         if(lc[z] == y) lc[z] = x;
 92         else rc[z] = x;
 93     if(lc[y] == x) rc[x] = y, lc[y] = w;
 94     else lc[x] = y, rc[y] = w;
 95     Update(y);
 96 }
 97 inline void Splay(int x, int anc)
 98 {
 99     Down(x);
100     while(fat[x] != anc)
101     {
102         if(fat[fat[x]] != anc)
103             if((lc[fat[fat[x]]] == fat[x]) == (lc[fat[x]] == x)) Turn(fat[x]);
104             else Turn(x);
105         Turn(x);
106     }
107     Update(x);
108     if(!anc) root = x;
109 }
110 int Build(int l, int r, int f)
111 {
112     int mid = l + r >> 1;
113     int k = id[mid];
114     fat[k] = f;
115     sam[k] = inf;
116     val[k] = pri[mid];
117     if(l == r) si[k] = 1;
118     if(l < mid) lc[k] = Build(l, mid - 1, k);
119     if(r > mid) rc[k] = Build(mid + 1, r, k);
120     Update(k);
121     return k;
122 }
123 inline int Find(int x)
124 {
125     int k = root;
126     while(true)
127     {
128         Down(k);
129         int sum = si[lc[k]] + 1;
130         if(sum == x) return k;
131         if(sum > x) k = lc[k];
132         else k = rc[k], x -= sum;
133     }
134 }
135 inline void Clear(int x)
136 {
137     lc[x] = rc[x] = fat[x] = 0;
138     rev[x] = 0, sam[x] = inf;
139 }
140 inline void Modify(int l, int r, int c)
141 {
142     int x = Find(l), y = Find(r);
143     Splay(x, 0), Splay(y, x);
144     int z = lc[y];
145     Change(z, c);
146     Update(y), Update(x);
147 }
148 inline void Insert(int l, int r, int n)
149 {
150     int x = Find(l), y = Find(r);
151     Splay(x, 0), Splay(y, x);
152     int cnt = n;
153     while(deln && cnt) id[cnt--] = del[deln--];
154     while(cnt) id[cnt--] = ++num;
155     int np = Build(1, n, 0);
156     Down(y);
157     lc[y] = np;
158     fat[np] = y;
159     Update(y), Update(x);
160 }
161 void Del(int x)
162 {
163     if(!x) return;
164     Del(lc[x]);
165     del[++deln] = x;
166     Del(rc[x]);
167     Clear(x);
168 }
169 inline void Del(int l, int r)
170 {
171     int x = Find(l), y = Find(r);
172     Splay(x, 0), Splay(y, x);
173     int z = lc[y];
174     lc[y] = 0;
175     Del(z);
176     Update(y), Update(x);
177 }
178 inline void Reverse(int l, int r)
179 {
180     int x = Find(l), y = Find(r);
181     Splay(x, 0), Splay(y, x);
182     int z = lc[y];
183     Rever(z);
184     Update(y), Update(x);
185 }
186 inline void Sum(int l, int r)
187 {
188     int x = Find(l), y = Find(r);
189     Splay(x, 0), Splay(y, x);
190     int z = lc[y];
191     printf("%d\n", sum[z]);
192 }
193 inline void Max(int l, int r)
194 {
195     int x = Find(l), y = Find(r);
196     Splay(x, 0), Splay(y, x);
197     int z = lc[y];
198     printf("%d\n", kmax[z]);
199 }
200 char s[233];
201 int main()
202 {
203     Scan(n), Scan(m);
204     num = n + 2;
205     for(int i = 1; i <= n; ++i) Scan(pri[i + 1]);
206     for(int i = 1; i <= num; ++i) id[i] = i;
207     root = Build(1, num, 0);
208     int pos, tot, c, l, r;
209     while(m--)
210     {
211         scanf("%s", s);
212         switch(s[0])
213         {
214             case 'I':
215             {
216                 Scan(pos), Scan(tot);
217                 for(int i = 1; i <= tot; ++i) Scan(pri[i]);
218                 Insert(pos + 1, pos + 2, tot);
219                 break;
220             }
221             case 'D':
222             {
223                 Scan(pos), Scan(tot);
224                 Del(pos, pos + tot + 1);
225                 break;
226             }
227             case 'R':
228             {
229                 Scan(pos), Scan(tot);
230                 Reverse(pos, pos + tot + 1);
231                 break;
232             }
233             case 'G':
234             {
235                 Scan(pos), Scan(tot);
236                 Sum(pos, pos + tot + 1);
237                 break;
238             }
239             case 'M':
240             {
241                 if(s[4] == '-')
242                 {
243                     Scan(pos), Scan(tot), Scan(c);
244                     Modify(pos, pos + tot + 1, c);
245                 }
246                 else Max(1, si[root]);
247                 break;
248             }
249         }
250     }
251 }
posted @ 2017-05-24 15:49  草根柴鸡  阅读(160)  评论(0编辑  收藏  举报