NKOJ 3884 (NOI 2005) 维修数列(Splay)

P3884 NOI2005维修数列

问题描述

这里写图片描述

输入格式

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

输出格式

对于输入数据中的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 个数。 输入数据一定是正确的,即指定位置的数在数列中一定存在。

50%的数据中,任何时刻数列中最多含有 30 000 个数; 100%的数据中,任何时刻数列中最多含有 500 000 个数。

100%的数据中,任何时刻数列中任何一个数字均在[-1 000, 1 000]内。 100%的数据中,M ≤20 000,插入的数字总数不超过 4 000 000 个,输入文件 大小不超过 20MBytes。


Splay模板题,修改和翻转用lazy,维护区间和,考虑如何维护最大区间和,用类似线段树的方法解决即可。
注意当儿子为0时要特别小心。


代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<cstring>
#define N 8000005
#define max(a,b) ((a>b)?(a):(b))
using namespace std;
const int Inf=99999999;
int n,m,A[N],L,R;
int tot,rt,ls[N],rs[N],fa[N],si[N],v[N],lazy1[N],lazy2[N],lmax[N],rmax[N],Max[N],sum[N];
int GM(int x,int y,int z)
{
if(x>=y&&x>=z)return x;
if(y>=z)return y;
return z;
}
void MT(int p)
{
lmax[p]=GM(lmax[ls[p]],sum[ls[p]]+v[p],sum[ls[p]]+v[p]+lmax[rs[p]]);
rmax[p]=GM(rmax[rs[p]],sum[rs[p]]+v[p],sum[rs[p]]+v[p]+rmax[ls[p]]);
Max[p]=GM(Max[ls[p]],Max[rs[p]],max(0,lmax[rs[p]])+max(0,rmax[ls[p]])+v[p]);
sum[p]=sum[ls[p]]+sum[rs[p]]+v[p];
si[p]=si[ls[p]]+si[rs[p]]+1;
}
void PD(int p)
{
if(lazy1[p])
{
swap(ls[ls[p]],rs[ls[p]]);
swap(lmax[ls[p]],rmax[ls[p]]);
swap(ls[rs[p]],rs[rs[p]]);
swap(lmax[rs[p]],rmax[rs[p]]);
lazy1[ls[p]]^=1;
lazy1[rs[p]]^=1;
}
if(lazy2[p]!=Inf)
{
v[ls[p]]=v[rs[p]]=lazy2[p];
sum[ls[p]]=lazy2[p]*si[ls[p]];
sum[rs[p]]=lazy2[p]*si[rs[p]];
lmax[ls[p]]=rmax[ls[p]]=Max[ls[p]]=lazy2[p]>0?lazy2[p]*si[ls[p]]:lazy2[p];
lmax[rs[p]]=rmax[rs[p]]=Max[rs[p]]=lazy2[p]>0?lazy2[p]*si[rs[p]]:lazy2[p];
lazy2[ls[p]]=lazy2[rs[p]]=lazy2[p];
}
lazy1[p]=0;lazy2[p]=Inf;
}
void Zig(int x)
{
int y=fa[x],z=fa[y];
if(y==ls[z])ls[z]=x;else rs[z]=x;fa[x]=z;
ls[y]=rs[x];fa[rs[x]]=y;
rs[x]=y;fa[y]=x;
MT(y);MT(x);
}
void Zag(int x)
{
int y=fa[x],z=fa[y];
if(y==ls[z])ls[z]=x;else rs[z]=x;fa[x]=z;
rs[y]=ls[x];fa[ls[x]]=y;
ls[x]=y;fa[y]=x;
MT(y);MT(x);
}
void Splay(int x,int t)
{
int y,z;
while(fa[x]!=t)
{
y=fa[x];z=fa[y];
if(z)PD(z);
if(y)PD(y);
if(x)PD(x);
if(z!=t)
{
if(y==ls[z])
{
if(x==ls[y])Zig(y),Zig(x);
else Zag(x),Zig(x);
}
else
{
if(x==rs[y])Zag(y),Zag(x);
else Zig(x),Zag(x);
}
}
else if(x==ls[y])Zig(x);else Zag(x);
}
if(!t)rt=x;
}
int BT(int x,int y)
{
if(x>y)return 0;
int p=++tot;
lazy2[p]=Inf;
if(x==y&&x==0)L=p;
if(x==y&&x==n+1)R=p;
if(x<y)
{
int mid=x+y>>1;
if(mid==0)L=p;
if(mid==n+1)R=p;
v[p]=A[mid];
ls[p]=BT(x,mid-1);
rs[p]=BT(mid+1,y);
fa[ls[p]]=p;
fa[rs[p]]=p;
MT(p);
}
else v[p]=sum[p]=lmax[p]=rmax[p]=Max[p]=A[x],si[p]=1;
return p;
}
int Find(int k)
{
int p=rt;
while(p)
{
PD(p);
if(si[ls[p]]+1==k)return p;
if(si[ls[p]]>=k)p=ls[p];
else k-=si[ls[p]]+1,p=rs[p];
}
return p;
}
void INS()
{
int i,x,y,a,b;
scanf("%d%d",&x,&y);
for(i=1;i<=y;i++)scanf("%d",&A[i]);
a=Find(x+1);b=Find(x+2);
Splay(a,0);Splay(b,rt);
tot++;
v[tot]=sum[tot]=lmax[tot]=rmax[tot]=Max[tot]=A[1];
lazy2[tot]=Inf;si[tot]=1;
for(i=2;i<=y;i++)
{
tot++;
v[tot]=A[i];
lazy2[tot]=Inf;
ls[tot]=tot-1;
fa[tot-1]=tot;
MT(tot);
}
fa[tot]=b;ls[b]=tot;MT(b);MT(a);
}
void DEL()
{
int x,y,a,b;
scanf("%d%d",&x,&y);
a=Find(x);b=Find(x+y+1);
Splay(a,0);Splay(b,rt);
fa[ls[rs[rt]]]=0;
ls[rs[rt]]=0;
MT(rs[rt]);
MT(rt);
}
void CHA()
{
int x,y,z,a,b,p;
scanf("%d%d%d",&x,&y,&z);
a=Find(x);b=Find(x+y+1);
Splay(a,0);Splay(b,rt);
p=ls[rs[rt]];
lazy2[p]=z;
v[p]=z;sum[p]=z*si[p];
lmax[p]=rmax[p]=Max[p]=z>0?z*si[p]:z;
MT(rs[rt]);
MT(rt);
}
void REV()
{
int x,y,a,b,p;
scanf("%d%d",&x,&y);
a=Find(x);b=Find(x+y+1);
Splay(a,0);Splay(b,rt);
p=ls[rs[rt]];
lazy1[p]^=1;
swap(ls[p],rs[p]);
swap(lmax[p],rmax[p]);
MT(rs[rt]);
MT(rt);
}
void SUM()
{
int x,y,a,b;
scanf("%d%d",&x,&y);
a=Find(x);b=Find(x+y+1);
Splay(a,0);Splay(b,rt);
printf("%d\n",sum[ls[rs[rt]]]);
}
void MAX()
{
Splay(L,0);Splay(R,rt);
printf("%d\n",Max[ls[rs[rt]]]);
}
int main()
{
int i,x,y,z;char s[15];
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)scanf("%d",&A[i]);
rt=BT(0,n+1);
while(m--)
{
scanf("%s",s);
if(s[2]=='S')INS();
if(s[2]=='L')DEL();
if(s[2]=='K')CHA();
if(s[2]=='V')REV();
if(s[2]=='T')SUM();
if(s[2]=='X')MAX();
}
}