今天比较闲所以把这个题拿来练练手。从晚9点写到12点半然后改到凌晨2点终于改完。。。。最后还被大神说是写得快的了 说byvoid大神写了两个早上加一个下午。。。。
前几个操作都很简单之接搞就可以了。对于最后一个操作我们可以用类似于线段树区间合并的标记来做。lmax和rmax,mmax表示左边区间以左开头和以右结尾和中间的最大和。
rever后记得要swap(lmax,rmax)哟,还有要用一个内存池不然会爆内存。。。。。
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
#define maxn 1010000
#define INF 0x3f3f3f3f
inline int getint()
{
int res=0,f=1;char c;
while(c=getchar(),c<'0'||c>'9'){if(c=='-')f=-1;}
res=c-'0';
while(c=getchar(),c>='0'&&c<='9')res=res*10+c-'0';
return res*f;
}
int tr[maxn][2],fa[maxn],root,n,m;
bool rev[maxn],tag[maxn];
int sum[maxn],lmax[maxn],rmax[maxn],mmax[maxn],v[maxn],a[maxn];
int sta[maxn],top,id[maxn],siz[maxn],cnt;
void pushup(int rt)
{
int l=tr[rt][0],r=tr[rt][1];
siz[rt]=siz[l]+siz[r]+1;
sum[rt]=sum[l]+sum[r]+v[rt];
lmax[rt]=max(lmax[l],sum[l]+v[rt]+lmax[r]);
rmax[rt]=max(rmax[r],sum[r]+v[rt]+rmax[l]);
mmax[rt]=max(mmax[l],mmax[r]);
mmax[rt]=max(mmax[rt],rmax[l]+v[rt]+lmax[r]);
}
void pushdown(int rt)
{
int l=tr[rt][0],r=tr[rt][1];
if(tag[rt])
{
tag[rt]=rev[rt]=0;
if(l)
{
tag[l]=1;v[l]=v[rt];
sum[l]=v[l]*siz[l];
}
if(r)
{
tag[r]=1;v[r]=v[rt];
sum[r]=v[r]*siz[r];
}
if(v[rt]>=0)
{
if(l) mmax[l]=rmax[l]=lmax[l]=sum[l];
if(r) mmax[r]=rmax[r]=lmax[r]=sum[r];
}
else
{
if(l) rmax[l]=lmax[l]=0,mmax[l]=v[rt];
if(r) rmax[r]=lmax[r]=0,mmax[r]=v[rt];
}
}
if(rev[rt])
{
rev[rt]^=1;rev[r]^=1;rev[l]^=1;
swap(lmax[l],rmax[l]);swap(lmax[r],rmax[r]);
swap(tr[l][0],tr[l][1]);swap(tr[r][0],tr[r][1]);
//pushup(rt);
}
}
void rotate(int x,int &rt)
{
int l,r,z,y;
y=fa[x];z=fa[y];
if(x==tr[y][0]) l=0;
else l=1;r=1^l;
if(rt==y) rt=x;
else
{
if(tr[z][0]==y) tr[z][0]=x;
else tr[z][1]=x;
}
fa[x]=z;fa[y]=x;fa[tr[x][r]]=y;
tr[y][l]=tr[x][r];tr[x][r]=y;
pushup(y);pushup(x);
}
void build(int l,int r,int f)
{
if(l>r)return;
int now=id[l],last=id[f];
if(l==r)
{
v[now]=mmax[now]=sum[now]=a[l];
fa[now]=last;siz[now]=1;
lmax[now]=rmax[now]=max(0,a[l]);
if(l<f)tr[last][0]=now;
else tr[last][1]=now;
return;
}
int mid=(l+r)>>1;now=id[mid];
build(l,mid-1,mid);build(mid+1,r,mid);
v[now]=a[mid];fa[now]=last;
pushup(now);
if(mid<f)tr[last][0]=now;
else tr[last][1]=now;
}
void splay(int x,int &rt)
{
int y,z;
while(x!=rt)
{
y=fa[x];z=fa[y];
if(y!=rt)
{
if((tr[y][0]==x)^(tr[z][0]==y)) rotate(x,rt);
else rotate(y,rt);
}
rotate(x,rt);
}
}
int select(int now,int rk)
{
if(rev[now]||tag[now]) pushdown(now);
int l=tr[now][0],r=tr[now][1];
int rak=siz[l]+1;
if(rak==rk) return now;
if(rak>rk) return select(l,rk);
else return select(r,rk-rak);
}
void clean(int x)
{
if(!x)return;
int l=tr[x][0],r=tr[x][1];
clean(l);clean(r);
fa[x]=tr[x][0]=tr[x][1]=0;
tag[x]=rev[x]=0;
top++;sta[top]=x;
}
void dele(int s,int b)
{
int x=select(root,s);
int y=select(root,s+b+1);
splay(x,root);splay(y,tr[x][1]);
clean(tr[y][0]);tr[y][0]=0;
pushup(y);pushup(x);
}
void query(int s,int b)
{
int x=select(root,s);
int y=select(root,s+b+1);
splay(x,root);splay(y,tr[x][1]);
printf("%d\n",sum[tr[y][0]]);
}
void solve_rever(int x)
{
if(tag[x]) return;
rev[x]^=1;
swap(tr[x][0],tr[x][1]);
swap(lmax[x],rmax[x]);
}
void rever(int s,int b)
{
int x=select(root,s);
int y=select(root,s+b+1);
splay(x,root);splay(y,tr[x][1]);
solve_rever(tr[y][0]);
pushup(y);pushup(x);
}
void solve_change(int x,int val)
{
tag[x]=1;v[x]=val;
sum[x]=siz[x]*v[x];
if(v[x]>=0)
{
mmax[x]=rmax[x]=lmax[x]=sum[x];
}
else
{
rmax[x]=lmax[x]=0;
mmax[x]=v[x];
}
}
void change(int s,int b,int val)
{
int x=select(root,s);
int y=select(root,s+b+1);
splay(x,root);splay(y,tr[x][1]);
solve_change(tr[y][0],val);
pushup(y);pushup(x);
}
void ins(int s,int b)
{
for(int i=1;i<=b;i++)
{
a[i]=getint();
if(top)
{
id[i]=sta[top];top--;
}
else cnt++,id[i]=cnt;
}
build(1,b,0);
int z=id[(b+1)>>1];
int x=select(root,s+1);
int y=select(root,s+2);
splay(x,root);splay(y,tr[root][1]);
fa[z]=y;tr[y][0]=z;
pushup(y);pushup(x);
}
int main()
{
n=getint();m=getint();
mmax[0]=-INF;
a[1]=a[n+2]=-INF;
for(int i=1;i<=n;i++)
a[i+1]=getint();
for(int i=1;i<=n+2;i++)
id[i]=i;
build(1,n+2,0);
root=(n+3)>>1;cnt=n+2;
char s[10];
int k,tot,val;
for(int i=1;i<=m;i++)
{
scanf("%s",s);
if(s[0]=='I')
{
k=getint();tot=getint();ins(k,tot);
}
if(s[0]=='D')
{
k=getint();tot=getint();dele(k,tot);
}
if(s[0]=='M')
{
if(s[2]=='K')
{
k=getint();tot=getint();val=getint();change(k,tot,val);
}
else
{
printf("%d\n",mmax[root]);
}
}
if(s[0]=='R')
{
k=getint();tot=getint();rever(k,tot);
}
if(s[0]=='G')
{
k=getint();tot=getint();query(k,tot);
}
}
return 0;
}
/*
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
*/