题目描述
请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏 中的下划线‘ _ ’表示实际输入文件中的空格)
输入格式:
输入文件的第 1 行包含两个数 N 和 M,N 表示初始时数列中数的个数,M 表示要进行的操作数目。 第 2 行包含 N 个数字,描述初始时的数列。 以下 M 行,每行一条命令,格式参见问题描述中的表格
输出格式:
对于输入数据中的 GET-SUM 和 MAX-SUM 操作,向输出文件依次打印结 果,每个答案(数字)占一行。
输入样例#1:
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:
-1 10 1 10
说明
你可以认为在任何时刻,数列中至少有 1 个数。
输入数据一定是正确的,即指定位置的数在数列中一定存在。
50%的数据中,任何时刻数列中最多含有 30 000 个数;
100%的数据中,任何时刻数列中最多含有 500 000 个数。
100%的数据中,任何时刻数列中任何一个数字均在[-1 000, 1 000]内。
100%的数据中,M ≤20 000,插入的数字总数不超过 4 000 000 。
Splay模板 + 类似线段树区间合并的东西
#include<bits/stdc++.h>
#define N 5000005
#define lc t[x].ch[0]
#define rc t[x].ch[1]
using namespace std;
int n,m,root,tot,a[N],p[N]; char ch[20];
struct Node{
int ch[2],fa,val,size;
int tag,lazy;
int lmax,rmax,Max,sum;
}t[N];
int read(){
int cnt=0,f=1;char ch=0;
while(!isdigit(ch)){ch=getchar();if(ch=='-')f=-1;}
while(isdigit(ch))cnt=cnt*10+(ch-'0'),ch=getchar();
return cnt*f;
}
void Update(int x,int d){
t[x].val=d,t[x].sum=d*t[x].size,t[x].lazy+=d;
t[x].lmax=t[x].rmax=t[x].Max=max(d,d*t[x].size);
}
void Pushup(int x){
t[x].size=t[lc].size+t[rc].size+1;
t[x].sum=t[lc].sum+t[x].val+t[rc].sum;
t[x].Max=max( max(t[lc].Max,t[rc].Max) , max(t[lc].rmax,0) + t[x].val + max(0,t[rc].lmax) );
t[x].lmax=max(t[lc].lmax,t[lc].sum + t[x].val + max(0,t[rc].lmax));
t[x].rmax=max(t[rc].rmax,t[rc].sum + t[x].val + max(0,t[lc].rmax));
}
int Build(int l,int r,int fa){
if(l>r) return 0;
int mid=(l+r)>>1,x=++tot; p[x]=mid; t[x].size=1;
t[x].fa=fa,t[x].lmax=t[x].rmax=t[x].Max=t[x].sum=t[x].val=a[mid];
lc=Build(l,mid-1,x),rc=Build(mid+1,r,x);
Pushup(x); return x;
}
void Swap(int x){
swap(lc,rc);
swap(t[x].lmax,t[x].rmax);
t[x].tag^=1;
}
void Pushdown(int x){
if(t[x].tag){
if(lc) Swap(lc);
if(rc) Swap(rc);
t[x].tag=0;
}
if(t[x].lazy){
if(lc) Update(lc,t[x].lazy);
if(rc) Update(rc,t[x].lazy);
t[x].lazy=0;
}
}
void Pushpath(int x){
if(t[x].fa) Pushpath(t[x].fa);
Pushdown(x);
}
void rotate(int x){
int y=t[x].fa,z=t[y].fa;
int k=(t[y].ch[1]==x);
t[z].ch[t[z].ch[1]==y]=x;
t[x].fa=z;
t[y].ch[k]=t[x].ch[k^1];
t[t[x].ch[k^1]].fa=y;
t[x].ch[k^1]=y;
t[y].fa=x;
Pushup(y),Pushup(x);
}
void Splay(int x,int goal){
Pushpath(x);
while(t[x].fa!=goal){
int y=t[x].fa,z=t[y].fa;
if(z!=goal)
(t[z].ch[0]==y)^(t[y].ch[0]==x)?rotate(x):rotate(y);
rotate(x);
}if(goal==0) root=x;
}
int Find(int x,int k){
Pushdown(x);
if(t[lc].size>=k) return Find(lc,k);
else if(t[lc].size+1<k) return Find(rc,k-t[lc].size-1);
return x;
}
int main(){
n=read(),m=read();
for(int i=2;i<=n+1;i++) a[i]=read();
a[1]=a[n+2]=-0x3fffffff; root=Build(1,n+2,0);
while(m--){
scanf("%s",ch);
if(ch[0]=='I'){
int x=read(),T=read();
x=Find(root,x+1); Splay(x,0);
int y=Find(rc,1); Splay(y,x);
for(int i=1;i<=T;i++) a[i]=read();
int o=Build(1,T,y);
t[y].ch[0]=o;
Pushup(y),Pushup(x);
}
if(ch[0]=='D'){
int x=read(),T=read();
x=Find(root,x); Splay(x,0);
int y=Find(rc,T+1); Splay(y,x);
t[t[y].ch[0]].fa=0,t[y].ch[0]=0;
Pushup(y),Pushup(x);
}
if(ch[2]=='K'){
int x=read(),T=read(),val=read();
x=Find(root,x); Splay(x,0);
int y=Find(rc,T+1); Splay(y,x);
Update(t[y].ch[0],val);
Pushup(y),Pushup(x);
}
if(ch[0]=='R'){
int x=read(),T=read();
x=Find(root,x); Splay(x,0);
int y=Find(rc,T+1); Splay(y,x);
Swap(t[y].ch[0]);
t[t[y].ch[0]].tag^=1;
Pushup(y),Pushup(x);
}
if(ch[0]=='G'){
int x=read(),T=read();
x=Find(root,x); Splay(x,0);
int y=Find(rc,T+1);
Splay(y,x);
printf("%d\n",t[t[y].ch[0]].sum);
}
if(ch[2]=='X') printf("%d\n",t[root].Max);
}
return 0;
}