Description
Input
输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目。
第2行包含N个数字,描述初始时的数列。
以下M行,每行一条命令,格式参见问题描述中的表格。
任何时刻数列中最多含有500 000个数,数列中任何一个数字均在[-1 000, 1 000]内。
插入的数字总数不超过4 000 000个,输入文件大小不超过20MBytes。
Output
对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行。
Sample Input
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
10
1
10
HINT
Source
这题是splay里的魔鬼题了吧。。调了好久QAQ
最终在大牛help下AC(%%%)
对于操作1,首先构造一个x~y的区间(也就是split(x,y)分离过程),然后直接插入。
对于操作2,split(x,x+tot-1),然后将以对应区间为根的子树删除。
对于操作3,split出区间后,在子树的根上加一个tag来标记更新。
值得注意的是,加上这个tag之后,就不需要rev(旋转)标记了。
对于操作4,同上,加一个rev标记。
对于操作5,在整棵树上的每一个点加上一个sum(),sum(u)=sum(L)+sum(R)+num(u),L和R是u儿子,
如此维护即可。
对于操作6,略有麻烦。我们需要维护三个信息:一段区间的最大前缀lx,一段区间的最大后缀rx,
以及一段区间本身的最大子列和mx(对了,子列是连续的);
维护的方法:
mx(u)=max{mx(L),mx(R),rx(L)+lx(R)+num(u)}
lx(u)=max{lx(L),sum(L)+num(u)+lx(R)}
rx(u)=max(rx(R),sum(R)+num(u)+rx(L)}
这种模板题还是要。。看代码吧(QAQ)
#include<bits/stdc++.h>
using namespace std;
const int
NN=500000+5,
MM=5000000+5,
overroot=0;
int n,m,top,root;
int id[NN],a[NN],stk[MM];
struct Tree{
int son[2],pre,sz,num,sum,mx,lx,rx;
bool tag,rev;
}tree[NN];
inline int read(){
int x=0,f=1;char ch=getchar();
while (ch<'0' || ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while (ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
inline void up(int u){
if (u){
int l=tree[u].son[0],r=tree[u].son[1];
tree[u].sz=1+tree[l].sz+tree[r].sz;
tree[u].sum=tree[u].num+tree[l].sum+tree[r].sum;
tree[u].mx=max(tree[l].mx,tree[r].mx);
tree[u].mx=max(tree[u].mx,tree[l].rx+tree[r].lx+tree[u].num);
tree[u].lx=max(tree[l].lx,tree[l].sum+tree[r].lx+tree[u].num);
tree[u].rx=max(tree[r].rx,tree[r].sum+tree[l].rx+tree[u].num);
}
}
inline void down(int u){
if (u){
int l=tree[u].son[0],r=tree[u].son[1];
if (tree[u].tag){
tree[l].tag=1,tree[l].num=tree[u].num,tree[l].sum=tree[u].num*tree[l].sz;
tree[r].tag=1,tree[r].num=tree[u].num,tree[r].sum=tree[u].num*tree[r].sz;
if (tree[u].num>=0){
tree[l].mx=tree[l].lx=tree[l].rx=tree[l].sum;
tree[r].mx=tree[r].lx=tree[r].rx=tree[r].sum;
} else{
tree[l].mx=tree[l].num; tree[l].lx=tree[l].rx=0;
tree[r].mx=tree[r].num; tree[r].lx=tree[r].rx=0;
}
tree[u].tag=tree[u].rev=0;
}
if (tree[u].rev){
swap(tree[l].son[0],tree[l].son[1]);
swap(tree[r].son[0],tree[r].son[1]);
swap(tree[l].lx,tree[l].rx);
swap(tree[r].lx,tree[r].rx);
tree[l].rev^=1; tree[r].rev^=1;
tree[u].rev=0;
}
}
}
int getkth(int x,int k){
down(x);
int tmp=tree[tree[x].son[0]].sz;
if (tmp+1==k) return x;
if (k<=tmp) return getkth(tree[x].son[0],k);
else return getkth(tree[x].son[1],k-tmp-1);
}
inline void Rotate(int x,int f){
int y=tree[x].pre;
tree[y].son[!f]=tree[x].son[f];
tree[tree[x].son[f]].pre=y;
tree[x].pre=tree[y].pre;
if (tree[x].pre!=overroot) tree[tree[x].pre].son[tree[tree[x].pre].son[1]==y]=x;
tree[x].son[f]=y;
tree[y].pre=x;
up(y);
}
void splay(int x,int goal){
while (tree[x].pre!=goal){
int y=tree[x].pre,z=tree[y].pre;
down(z); down(y); down(x);
if (z==goal) Rotate(x,tree[y].son[0]==x);
else{
int f=tree[z].son[0]==y;
if (tree[y].son[f]==x) Rotate(x,!f);
else Rotate(y,f);
Rotate(x,f);
}
}
up(x);
if (goal==overroot) root=x;
}
inline int split(int a,int b){
int x=getkth(root,a),
y=getkth(root,b+2);
splay(x,overroot);
splay(y,x);
return tree[tree[root].son[1]].son[0];
}
void del(int u){
if (!u) return;
stk[++top]=u;
del(tree[u].son[0]);
del(tree[u].son[1]);
tree[u].son[0]=tree[u].son[1]=tree[u].pre=
tree[u].tag=tree[u].rev=0;
}
int build(int l,int r){
if (l>r) return 0;
if (l==r){
tree[id[l]].sum=tree[id[l]].num=a[l];
tree[id[l]].sz=1;
if (a[l]>=0) tree[id[l]].lx=tree[id[l]].rx=tree[id[l]].mx=a[l];
else tree[id[l]].lx=tree[id[l]].rx=0,tree[id[l]].mx=a[l];
return l;
}
int mid=(l+r)>>1;
tree[id[mid]].son[0]=id[build(l,mid-1)];
tree[id[mid]].son[1]=id[build(mid+1,r)];
int L=tree[id[mid]].son[0],R=tree[id[mid]].son[1];
if (L) tree[L].pre=id[mid];
if (R) tree[R].pre=id[mid];
tree[id[mid]].num=a[mid];
up(id[mid]);
return mid;
}
void solve(){
char t[11];
scanf("%s",t);
if (t[0]=='M' && t[1]=='A' && t[2]=='X'){
printf("%d\n",tree[root].mx);
return;
}
int x,y;
if (t[0]=='G'){
x=read(); y=read();
x=split(x,x+y-1);
printf("%d\n",tree[x].sum);
}
if (t[0]=='R'){
x=read(); y=read();
x=split(x,x+y-1);
y=tree[x].pre;
if (tree[x].tag) return;
tree[x].rev^=1;
swap(tree[x].lx,tree[x].rx);
swap(tree[x].son[0],tree[x].son[1]);
up(y); up(tree[y].pre);
}
int tt;
if (t[0]=='M'){
x=read(); y=read(); tt=read();
x=split(x,x+y-1);
y=tree[x].pre;
tree[x].tag=1; tree[x].num=tt;
tree[x].sum=tt*tree[x].sz;
if (tt>=0) tree[x].lx=tree[x].rx=tree[x].mx=tree[x].sum;
else tree[x].lx=tree[x].rx=0,tree[x].mx=tt;
up(y); up(tree[y].pre);
}
if (t[0]=='D'){
x=read(); y=read();
x=split(x,x+y-1);
y=tree[x].pre;
del(x);
tree[y].son[0]=0;
up(y); up(tree[y].pre);
}
if (t[0]=='I'){
x=read(); y=read();
for (int i=1;i<=y;i++) a[i]=read();
for (int i=1;i<=y;i++)
if (top) id[i]=stk[top--];
else id[i]=++n;
int xx=getkth(root,x+1),yy=getkth(root,x+2);
splay(xx,overroot); splay(yy,root);
int tmp=id[build(1,y)];
tree[yy].son[0]=tmp;
tree[tmp].pre=yy;
up(yy); up(xx);
}
}
int main(){
n=read(),m=read();
tree[0].mx=a[1]=a[n+2]=-100000000;
for (int i=1;i<=n;i++) a[i+1]=read();
n+=2;
for (int i=1;i<=n;i++) id[i]=i;
root=build(1,n);
while (m--) solve();
return 0;
}