description
给出n个数a[i],要求你支持共m次操作,种类如下:
1.I x y : 在第x个数前插入一个数y;
2.D x : 删除第x个数;
3.R x y : 把第x个数改成y;
4.Q x y : 输出max{a[i] + a[i + 1] + … + a[j] | x<=i<=j<=y}。
analysis
-
挺久没认真搞过 s p l a y splay splay,一天搞自动机加 s p l a y splay splay码量极大
影响发量 -
用 s p l a y splay splay维护前面三个操作不难,这题没有翻转标记所以不用翻转
-
主要是第四个询问区间最大子段和,需要画图思考一下
-
想象一下,一个区间的最大子段和,有几种情况
-
一是左儿子区间的从最左开始的子段和最大
-
二是右儿子区间的从最右开始的子段和最大
-
三是跨左右儿子的子段和最大
-
于是用 s p l a y splay splay维护左子段最大和、右子段最大和、区间权值和,就可以维护该子段最大和了
-
不懂可见程序下传数据 u p d a t e update update处的更新
code
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define MAXN 200005
#define INF 1000000007
#define ll long long
#define fo(i,a,b) for (ll i=a;i<=b;++i)
#define fd(i,a,b) for (ll i=a;i>=b;--i)
using namespace std;
ll tr[MAXN][2],size[MAXN],fa[MAXN];
ll val[MAXN],sum[MAXN],lx[MAXN],rx[MAXN],mx[MAXN];
ll a[MAXN],stack[MAXN];
ll n,m,root,tot1,tot2;
inline ll read()
{
ll x=0,f=1;char ch=getchar();
while (ch<'0' || '9'<ch){if (ch=='-')f=-1;ch=getchar();}
while ('0'<=ch && ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
inline ll max(ll x,ll y)
{
return x>y?x:y;
}
inline void newnode(ll &x,ll y,ll z)
{
x=tot2?stack[tot2--]:++tot1;
tr[x][0]=tr[x][1]=0,fa[x]=z,size[x]=1;
val[x]=sum[x]=lx[x]=rx[x]=mx[x]=y;
}
inline ll find(ll x,ll y)
{
if (y==size[tr[x][0]]+1)return x;
else return y<=size[tr[x][0]]?find(tr[x][0],y):find(tr[x][1],y-size[tr[x][0]]-1);
}
inline void update(ll x)
{
size[x]=size[tr[x][0]]+size[tr[x][1]]+1;
sum[x]=sum[tr[x][0]]+sum[tr[x][1]]+val[x];
lx[x]=max(lx[tr[x][0]],max(sum[tr[x][0]]+val[x],sum[tr[x][0]]+val[x]+lx[tr[x][1]]));
rx[x]=max(rx[tr[x][1]],max(sum[tr[x][1]]+val[x],sum[tr[x][1]]+val[x]+rx[tr[x][0]]));
mx[x]=max(max(mx[tr[x][0]],mx[tr[x][1]]),max(rx[tr[x][0]],0)+max(lx[tr[x][1]],0)+val[x]);
}
inline void build(ll &x,ll l,ll r,ll y)
{
if (l>r)return;
ll mid=(l+r)>>1;
newnode(x,a[mid],y);
build(tr[x][0],l,mid-1,x),build(tr[x][1],mid+1,r,x);
update(x);
}
inline void init()
{
tot1=tot2=root=0;
val[0]=sum[0]=tr[0][0]=tr[0][1]=fa[0]=0;
lx[0]=rx[0]=mx[0]=val[0]=-INF;
newnode(root,-INF,0),newnode(tr[root][1],-INF,root);
build(tr[tr[root][1]][0],1,n,tr[root][1]);
update(tr[root][1]),update(root);
}
inline ll lr(ll x)
{
return tr[fa[x]][1]==x;
}
inline void rotate(ll x)
{
ll y=fa[x],k=lr(x);
tr[y][k]=tr[x][!k];
if (tr[x][!k])fa[tr[x][!k]]=y;
fa[x]=fa[y];
if (fa[y])tr[fa[y]][lr(y)]=x;
tr[x][!k]=y,fa[y]=x;
update(y),update(x);
}
inline void splay(ll x,ll y)
{
while (fa[x]!=y)
{
if (fa[fa[x]]!=y)
{
if (lr(x)==lr(fa[x]))rotate(fa[x]);
else rotate(x);
}
rotate(x);
}
if (y==0)root=x;
}
inline void insert(ll x,ll y)
{
ll l=find(root,x),r=find(root,x+1);
splay(l,0),splay(r,root);
newnode(tr[tr[root][1]][0],y,tr[root][1]);
update(tr[root][1]),update(root);
}
inline void erase(ll x)
{
ll l=find(root,x),r=find(root,x+2);
splay(l,0),splay(r,root);
stack[++tot2]=tr[tr[root][1]][0];
tr[tr[root][1]][0]=0;
update(tr[root][1]),update(root);
}
inline void replace(ll x,ll y)
{
ll l=find(root,x+1);
val[l]=y,splay(l,0);
}
inline ll query(ll x,ll y)
{
ll l=find(root,x),r=find(root,y+2);
splay(l,0),splay(r,root);
return mx[tr[tr[root][1]][0]];
}
int main()
{
freopen("T3.in","r",stdin);
n=read();
fo(i,1,n)a[i]=read();
init();
m=read(),scanf("\n");
while (m--)
{
char ch=getchar();ll x=read();
if (ch=='I')insert(x,read());
else if (ch=='D')erase(x);
else if (ch=='R')replace(x,read());
else printf("%lld\n",query(x,read()));
}
return 0;
}