这题…mdzz。我想打人。


【分析】
六种操作都比较基本…然而拼到一起就很难了呢呵呵。(对我来说很难)

大家直接参考代码吧。注意一点就是要把删除节点的编号存起来,insert的时候用这些节点,要不然会RE RE RE RE RE RE RE RE RE RERE


【代码】

#include<iostream>
#include<cstring>
#include<cstdio>
#define ll long long
#define inf 0x3f3f3f3f
#define M(a) memset(a,-inf,sizeof a)
#define fo(i,j,k) for(i=j;i<=k;i++)
using namespace std;
const int mxn=500000;
int n,m,sz,opt,root,top;
int a[mxn],c[mxn],f[mxn],ch[mxn][2],key[mxn],size[mxn],tag[mxn],rub[mxn];
int reverse[mxn],sum[mxn],lmx[mxn],rmx[mxn],mx[mxn];
inline int get(int x)
{
if(ch[f[x]][1]==x) return 1;return 0;
}
inline void update(int now)
{
if(!now) return;
size[now]=1;
int l=ch[now][0],r=ch[now][1];
if(l) size[now]+=size[l];
if(r) size[now]+=size[r];
lmx[now]=max(lmx[l],sum[l]+key[now]+max(0,lmx[r]));
rmx[now]=max(rmx[r],sum[r]+key[now]+max(0,rmx[l]));
mx[now]=max(max(mx[l],mx[r]),max(0,rmx[l])+max(0,lmx[r])+key[now]);
sum[now]=sum[l]+sum[r]+key[now];
}
inline void rev(int x)
{
if (!x) return;
swap(lmx[x],rmx[x]);
swap(ch[x][0],ch[x][1]);
reverse[x]^=1;
}
inline void replace(int x,int d)
{
if (!x) return;
key[x]=d,sum[x]=d*size[x];
lmx[x]=rmx[x]=mx[x]=max(d,d*size[x]);
tag[x]=1;
}
inline void pushdown(int x)
{
if(reverse[x])
{
if(ch[x][0]) rev(ch[x][0]);
if(ch[x][1]) rev(ch[x][1]);
reverse[x]=0;
}
if (tag[x])
{
if(ch[x][0]) replace(ch[x][0],key[x]);
if(ch[x][1]) replace(ch[x][1],key[x]);
tag[x]=0;
}
}
inline void rotate(int x)
{
pushdown(x);
int fa=f[x],fafa=f[fa],which=get(x);
ch[fa][which]=ch[x][which^1],f[ch[fa][which]]=fa;
ch[x][which^1]=fa,f[fa]=x;
f[x]=fafa;
if(fafa) ch[fafa][ch[fafa][1]==fa]=x;
update(fa),update(x);
}
inline void splay(int x,int lastfa)
{
for(int fa;(fa=f[x])!=lastfa;rotate(x))
if(f[fa]!=lastfa) rotate(get(x)==get(fa)?fa:x);
if(!lastfa) root=x;
}
inline int build(int fa,int l,int r)
{
if(l>r) return 0;
int now,mid=l+r>>1;;
if(!top) now=++sz;
else now=rub[top--];
sum[now]=lmx[now]=rmx[now]=mx[now]=key[now]=a[mid],f[now]=fa,size[now]=1;
tag[now]=reverse[now]=0;
ch[now][0]=build(now,l,mid-1);
ch[now][1]=build(now,mid+1,r);
update(now);
return now;
}
inline int number(int x)
{
int now=root;
while(1)
{
pushdown(now);
if(ch[now][0] && x<=size[ch[now][0]]) now=ch[now][0];
else
{
if(x==size[ch[now][0]]+1) return now;
x=x-size[ch[now][0]]-1;
now=ch[now][1];pushdown(now);
}
}
}
inline void del(int x)
{
if(!x) return;
rub[++top]=x;
if(ch[x][0]) del(ch[x][0]);
if(ch[x][1]) del(ch[x][1]);
}
int main()
{
// freopen("rand.txt","r",stdin);
// freopen("mine.txt","w",stdout);
M(lmx),M(rmx),M(mx);
char str[105];
int i,j,k,x,y,z,w,tot,posi;
scanf("%d%d",&n,&m);
fo(i,2,n+1) scanf("%d",&a[i]);
a[1]=-inf,a[n+2]=-inf;
root=build(0,1,n+2);
while(m--)
{
scanf("%s",str);
if(str[0]=='I') //区间插入
{
scanf("%d%d",&posi,&tot);posi++;
fo(i,1,tot) scanf("%d",&a[i]);
x=number(posi),y=number(posi+1);
splay(x,0),splay(y,x);
int tmp=build(ch[root][1],1,tot);
ch[ch[root][1]][0]=tmp;
update(ch[ch[root][1]][0]);
update(ch[root][1]),update(root);
}
if(str[0]=='D') //区间删除
{
scanf("%d%d",&posi,&tot);posi++;
x=number(posi-1),y=number(posi+tot);
splay(x,0),splay(y,x);
del(ch[ch[root][1]][0]);
f[ch[ch[root][1]][0]]=0;ch[ch[root][1]][0]=0;
update(ch[root][1]),update(root);
}
if(str[0]=='M' && str[2]=='K') //区间修改
{
scanf("%d%d%d",&posi,&tot,&w);posi++;
x=number(posi-1),y=number(posi+tot);
splay(x,0),splay(y,x);
replace(ch[ch[root][1]][0],w);
update(ch[root][1]),update(root);
}
if(str[0]=='R') //区间翻转
{
scanf("%d%d",&posi,&tot);posi++;
x=number(posi-1),y=number(posi+tot);
splay(x,0),splay(y,x);
int tmp=ch[ch[root][1]][0];
rev(tmp);
update(ch[root][1]),update(root);
}
if(str[0]=='G') //区间求和
{
scanf("%d%d",&posi,&tot);posi++;
x=number(posi-1),y=number(posi+tot);
splay(x,0),splay(y,x);
pushdown(ch[ch[root][1]][0]);
update(ch[root][1]),update(root);
printf("%d\n",sum[ch[ch[root][1]][0]]);
}
if(str[0]=='M' && str[2]=='X')
{
printf("%d\n",mx[root]);
}
}
return 0;
}
/*
4 3
1 -1 -5 1
MAX_SUM
REVERSE 1 4
MAX_SUM
*/