BZOJ 1500 维修数列

Description

Input

输入文件的第1行包含两个数N和M,N表示初始时数列中数的个数,M表示要进行的操作数目。第2行包含N个数字,描述初始时的数列。以下M行,每行一条命令,格式参见问题描述中的表格。

Output

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

Sample Input

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

Sample Output

-1
10
1
10

HINT

Source

这题也是醉了~拍了两三天。。。看上去也就是个splay裸题。

最大字段和的维护:splay每个节点i记录从i的左子树最左起的最大字段和lb,右子树最右起的最大字段和rb,以及它所表示的整个区间的最大字段和。 lb[i]=max(lb[lc],sum[lc]+key[i]+lb[rc]),rb[i]=max(rb[rc],sum[rc]+key[i]+rb[lc]),wb[i]=max(wb[lc],wb[rc],rb[lc]+lb[rc]+key[i]),其中sum表示区间和,key表示该点的权值,lc与rc分别表示左右孩子。有许多细节请自己脑补。。。

  1 #include<queue>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<cstdio>
  5 #include<cstdlib>
  6 using namespace std;
  7
  8 #define maxn 500010
  9 #define inf (1 << 20)
 10 int n,m,TEMP[maxn],stack[maxn];
 11 queue <int> team;
 12
 13 inline int Max(int a,int b) {if (a > b) return a; return b;}
 14
 15 struct node
 16 {
 17     int fa[maxn],ch[maxn][2],key[maxn],sum[maxn],lm[maxn],rm[maxn],wm[maxn],size[maxn],cnt,root;
 18     bool rev[maxn],change[maxn];
 19
 20     inline int newnode()
 21     {
 22         if (team.empty()) return ++cnt;
 23         int ret = team.front(); team.pop();
 24         return ret;
 25     }
 26
 27     inline void updata(int a)
 28     {
 29         int lc = ch[a][0],rc = ch[a][1];
 30         pushdown(a); pushdown(lc); pushdown(rc);
 31         size[a] = size[lc] + size[rc] + 1;
 32         {
 33             sum[a] = sum[lc] + sum[rc] + key[a];
 34             lm[a] = rm[a] = wm[a] = -inf;
 35             lm[a] = Max(lm[a],sum[lc]+key[a]);
 36             lm[a] = Max(lm[a],sum[lc]+lm[rc]+key[a]);
 37             if (lc) lm[a] = Max(lm[a],lm[lc]);
 38             rm[a] = Max(rm[a],sum[rc]+key[a]);
 39             rm[a] = Max(rm[a],sum[rc]+rm[lc]+key[a]);
 40             if (rc) rm[a] = Max(rm[a],rm[rc]);
 41             wm[a] = Max(lm[a],rm[a]);
 42             wm[a] = Max(wm[a],rm[lc]+lm[rc]+key[a]);
 43             wm[a] = Max(wm[a],key[a]);
 44             wm[a] = Max(wm[a],rm[lc]+key[a]);
 45             wm[a] = Max(wm[a],lm[rc]+key[a]);
 46             if (rc) wm[a] = Max(wm[a],Max(lm[rc],wm[rc]));
 47             if (lc) wm[a] = Max(wm[a],Max(rm[lc],wm[lc]));
 48         }
 49     }
 50
 51     inline void pushdown(int a)
 52     {
 53         if (a == 0) { rev[a] = false; change[a] = false; return; }
 54         else
 55         {
 56             int lc = ch[a][0],rc = ch[a][1];
 57             if (rev[a])
 58             {
 59                 rev[a] = false;
 60                 swap(lm[a],rm[a]); swap(ch[a][0],ch[a][1]);
 61                 if (lc) rev[lc] ^= 1; if (rc) rev[rc] ^= 1;
 62             }
 63             if (change[a])
 64             {
 65                 change[a] = false;
 66                 if (lc) key[lc] = key[a],change[lc] = true;
 67                 if (rc) key[rc] = key[a],change[rc] = true;
 68                 sum[a] = key[a] * size[a];
 69                 if (key[a] >= 0) wm[a] = lm[a] = rm[a] = sum[a];
 70                 else wm[a] = lm[a] = rm[a] = key[a];
 71             }
 72         }
 73     }
 74
 75     inline int find(int rank,int have,int now)
 76     {
 77         pushdown(now);
 78         if (have+size[ch[now][0]]+1==rank) return now;
 79         if (have+size[ch[now][0]]+1>rank) return find(rank,have,ch[now][0]);
 80         else return find(rank,have+size[ch[now][0]]+1,ch[now][1]);
 81     }
 82
 83     inline void rotate(int x)
 84     {
 85         int y = fa[x],z = fa[y],l,r;
 86         if (ch[y][0] == x) l = 0; else l = 1; r = l ^ 1;
 87         if (z != 0)
 88         {
 89             if (ch[z][0] == y) ch[z][0] = x; else ch[z][1] = x;
 90         }
 91         fa[x] = z; fa[y] = x; fa[ch[x][r]] = y;
 92         ch[y][l] = ch[x][r]; ch[x][r] = y;
 93         updata(y); updata(x);
 94     }
 95
 96     inline void splay(int x,int aim)
 97     {
 98         int t = fa[aim],top = 0;
 99         for (int i = x;i != t;i = fa[i]) stack[++top] = i;
100         while (top) pushdown(stack[top--]);
101         while (fa[x] != t)
102         {
103             int y = fa[x],z = fa[y];
104             if (fa[y] != t)
105             {
106                 if ((ch[y][0] == x)^(ch[z][0] == y)) rotate(x);
107                 else rotate(y);
108             }
109             rotate(x);
110         }
111         if (aim == root) root = x;
112     }
113
114     inline int build(int l,int r)
115     {
116         int now = newnode(),mid = (l + r) >> 1;
117         ch[now][0] = ch[now][1] = 0;
118         rev[now] = change[now] = false;
119         if (l == r)
120         {
121             key[now] = TEMP[l]; updata(now);
122             return now;
123         }
124         if (l < mid)
125         {
126             ch[now][0] = build(l,mid - 1);
127             fa[ch[now][0]] = now;
128         }
129         if (mid < r)
130         {
131             ch[now][1] = build(mid + 1,r);
132             fa[ch[now][1]] = now;
133         }
134         key[now] = TEMP[mid];
135         updata(now);
136         return now;
137     }
138
139     inline void init(int l,int r)
140     {
141         root = build(l,r); int p;
142         p = find(n,0,root);
143         splay(p,root);
144         key[++cnt] = -inf;
145         fa[cnt] = p; ch[p][1] = cnt;
146         updata(cnt); updata(p);
147         p = find(1,0,root);
148         splay(p,root);
149         key[++cnt] = -inf;
150         fa[cnt] = p; ch[p][0] = cnt;
151         updata(cnt); updata(p);
152     }
153
154     inline void insert(int a,int b)
155     {
156         int p = find(a + 1,0,root),q = find(a + 2,0,root);
157         splay(p,root); splay(q,ch[p][1]);
158         int tr = build(1,b);
159         fa[tr] = q; ch[q][0] = tr;
160         updata(q); updata(p);
161     }
162
163     inline void rec(int now)
164     {
165         if (now == 0) return;
166         team.push(now);
167         rec(ch[now][0]); rec(ch[now][1]);
168     }
169
170     inline void del(int a,int b)
171     {
172         int p = find(a,0,root),q = find(a+b+1,0,root);
173         splay(p,root); splay(q,ch[p][1]);
174         rec(ch[q][0]);
175         fa[ch[q][0]] = 0; ch[q][0] = 0;
176         updata(q); updata(p);
177     }
178
179     inline void reverse(int a,int b)
180     {
181         int p = find(a,0,root),q = find(a+b+1,0,root);
182         splay(p,root); splay(q,ch[p][1]);
183         rev[ch[q][0]] ^= 1; pushdown(ch[q][0]);
184         updata(q); updata(p);
185     }
186
187     inline int getsum(int a,int b)
188     {
189         int p = find(a,0,root),q = find(a+b+1,0,root);
190         splay(p,root); splay(q,ch[p][1]);
191         return sum[ch[q][0]];
192     }
193
194     inline int maxsum() { updata(root); return wm[root];}
195
196     inline void modify(int a,int b,int c)
197     {
198         int p = find(a,0,root),q = find(a+b+1,0,root);
199         splay(p,root); splay(q,ch[p][1]);
200         key[ch[q][0]] = c; change[ch[q][0]] = true;
201         pushdown(ch[q][0]);
202         updata(ch[q][0]); updata(q); updata(p);
203         return;
204     }
205 }tree;
206
207 inline int read()
208 {
209     int x=0,f=1;char ch=getchar();
210     while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
211     while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
212     return x*f;
213 }
214
215 int main()
216 {
217     freopen("1500.in","r",stdin);
218     freopen("1500.out","w",stdout);
219     n = read(); m = read();
220     for (int i = 1;i <= n;++i) TEMP[i] = read();
221     tree.init(1,n);
222     char opt[20];
223     while (m--)
224     {
225         scanf("%s",opt);
226         if (opt[0] == ‘I‘)
227         {
228             int a = read(),b = read();
229             for (int i = 1;i <= b;++i) TEMP[i] = read();
230             tree.insert(a,b);
231         }
232         else if (opt[0] == ‘D‘)
233         {
234             int a = read(),b =read();
235             tree.del(a,b);
236         }
237         else if (opt[0] == ‘R‘)
238         {
239             int a = read(),b = read();
240             tree.reverse(a,b);
241         }
242         else if (opt[0] == ‘G‘)
243         {
244             int a = read(),b = read();
245             printf("%d\n",tree.getsum(a,b));
246         }
247         else if (opt[0] == ‘M‘&&opt[2] == ‘K‘)
248         {
249             int a = read(),b = read(),c = read();
250             tree.modify(a,b,c);
251         }
252         else printf("%d\n",tree.maxsum());
253     }
254     fclose(stdin); fclose(stdout);
255     return 0;
256 }

时间: 2024-12-25 20:53:17

BZOJ 1500 维修数列的相关文章

[代码] bzoj 1500 维修数列(无旋treap)

- 传送门 - http://www.lydsy.com/JudgeOnline/problem.php?id=1500 1500: [NOI2005]维修数列 Time Limit:?10 Sec??Memory Limit:?64 MB Submit:?15301??Solved:?5063 Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目. 第2行包含N个数字,描述初始时的数列. 以下M行,每行

【BZOJ】1500: [NOI2005]维修数列

[算法]splay [题解]数据结构 感谢Occult的模板>_<:HYSBZ 1500 维修数列 #include<cstdio> #include<cctype> #include<cstring> #include<queue> #include<algorithm> using namespace std; const int maxn=5e5+10,inf=0x3f3f3f3f; int n,m,root,a[maxn],t

BZOJ 1500: [NOI2005]维修数列

1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 12880  Solved: 4112[Submit][Status][Discuss] Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目.第2行包含N个数字,描述初始时的数列.以下M行,每行一条命令,格式参见问题描述中的表格.任何时刻数列中最多含有500 000个数,

BZOJ 1500: [NOI2005]维修数列( splay )

splay..... ------------------------------------------------------------------------ #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<queue> #define rep( i , n ) for( int i = 0 ; i < n ; ++

1500: [NOI2005]维修数列

1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 12952  Solved: 4138[Submit][Status][Discuss] Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目.第2行包含N个数字,描述初始时的数列.以下M行,每行一条命令,格式参见问题描述中的表格.任何时刻数列中最多含有500 000个数,

BZOJ1500: [NOI2005]维修数列[splay ***]

1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 12278  Solved: 3880[Submit][Status][Discuss] Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目.第2行包含N个数字,描述初始时的数列.以下M行,每行一条命令,格式参见问题描述中的表格.任何时刻数列中最多含有500 000个数,

BZOJ1500 维修数列

1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MB Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目.第2行包含N个数字,描述初始时的数列.以下M行,每行一条命令,格式参见问题描述中的表格.任何时刻数列中最多含有500 000个数,数列中任何一个数字均在[-1 000, 1 000]内.插入的数字总数不超过4 000 000个,输入文

bzoj1500 维修数列 splay

1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 10482  Solved: 3234[Submit][Status][Discuss] Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目.第2行包含N个数字,描述初始时的数列.以下M行,每行一条命令,格式参见问题描述中的表格.任何时刻数列中最多含有500 000个数,

Splay必做题 [NOI2005]维修数列

1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 6577  Solved: 1978[Submit][Status] Description Input 输入文件的第1行包含两个数N和M,N表示初始时数列中数的个数,M表示要进行的操作数目.第2行包含N个数字,描述初始时的数列.以下M行,每行一条命令,格式参见问题描述中的表格. Output 对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印