考虑维护一颗编号树
为了插入和删除的方便,我们选择将
a
[
0
]
=
a
[
n
+
1
]
=
−
i
n
f
a[0]=a[n+1]=-inf
a[0]=a[n+1]=−inf
表示填充上这个数,而且不影响最大子段和的答案。
先用 b u i l d build build建出来编号树(每次与中间为根节点,递归建左右子树)
int build(int faa,int l,int r)
{
//cout<<l<<" "<<r<<endl;
if (l>r) return 0;
int mid = l+r >> 1;
int now = newnode(a[mid]);
fa[now] = faa;
ch[now][0] = build(now,l,mid-1);
ch[now][1] = build(now,mid+1,r);
update(now);
return now;
}
考虑如果求最大子段和。
跟线段树类似,对于一颗
s
p
l
a
y
splay
splay要维护一个从底向上的最长后缀和和从上到下的最长前缀和
然后要注意本题不允许为空,所以每个点的
a
n
s
ans
ans的初始值是
v
a
l
[
x
]
val[x]
val[x]
合并和线段树类似,要注意更新的时候,到当前点,不一定要到另一个子树中,以右子树为例子,维护从底向上的后缀和,要考虑右子树的和加上当前点,或者加上当前点和左子树的后缀和。
void update(int x)
{
siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+val[x];
ans[x]=val[x];
if (ch[x][0] && ch[x][1])
{
hmy[x]=max(hmy[ch[x][1]],val[x]+sum[ch[x][1]]+hmy[ch[x][0]]);
hmy[x]=max(hmy[x],val[x]+sum[ch[x][1]]);
ymh[x]=max(ymh[ch[x][0]],val[x]+sum[ch[x][0]]+ymh[ch[x][1]]);
ymh[x]=max(ymh[x],val[x]+sum[ch[x][0]]);
ans[x]=max(ans[ch[x][0]],ans[ch[x][1]]);
ans[x]=max(hmy[x],ans[x]);
ans[x]=max(ans[x],ymh[x]);
ans[x]=max(ans[x],ymh[ch[x][1]]+val[x]+hmy[ch[x][0]]);
ans[x]=max(ans[x],ymh[ch[x][1]]+val[x]);
ans[x]=max(ans[x],hmy[ch[x][0]]+val[x]);
}
else
{
if (ch[x][0])
{
hmy[x]=max(val[x],val[x]+hmy[ch[x][0]]);
ymh[x]=max(ymh[ch[x][0]],sum[ch[x][0]]+val[x]);
ans[x]=max(hmy[x],ymh[x]);
ans[x]=max(ans[x],ans[ch[x][0]]);
}
else
{
if (ch[x][1])
{
hmy[x]=max(hmy[ch[x][1]],sum[ch[x][1]]+val[x]);
ymh[x]=max(val[x],val[x]+ymh[ch[x][1]]);
ans[x]=max(hmy[x],ymh[x]);
ans[x]=max(ans[x],ans[ch[x][1]]);
}
else
{
hmy[x]=ymh[x]=ans[x]=val[x];
}
}
}
ans[x]=max(ans[x],val[x]);
}
对于插入操作,我们只需要找到第 p o s pos pos和第 p o s + 2 pos+2 pos+2分别转到根和右儿子即可。
void insert(int pos,int x)
{
int qq = kth(pos+1);
int hj = kth(pos+2);
splay(qq,0);
splay(hj,qq);
int now = newnode(x);
ch[hj][0]=now;
fa[now]=hj;
splay(now,0);
}
这里为了节省空间,可以使用内存池,就是把用过的编号放到一个 v e c t o r vector vector里面,每次用的时候,首先去调用 v e c t o r vector vector里面的编号。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#include<cmath>
#include<map>
#include<set>
#define pb push_back
#define mk make_pair
#define ll long long
#define lson ch[x][0]
#define rson ch[x][1]
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
const int maxn = 3e5+1e2;
const int inf = -1e9;
int ch[maxn][2];
int siz[maxn];
int n,m;
int fa[maxn];
int sum[maxn];
int ymh[maxn],hmy[maxn]; //
int ans[maxn];
int val[maxn];
int root;
vector<int> rb;
int tot;
int a[maxn];
int newnode(int x)
{
int now = 0;
if (rb.empty())
{
++tot;
now = tot;
}
else
{
now = rb.back();
rb.pop_back();
}
//now = ++tot;
val[now]=ans[now]=ymh[now]=hmy[now]=x;
siz[now]=1;
return now;
}
void delnode(int x)
{
ans[x]=ymh[x]=hmy[x]=sum[x]=siz[x]=fa[x]=ch[x][0]=ch[x][1]=0;
val[x]=0;
rb.pb(x);
}
void update(int x)
{
siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+val[x];
ans[x]=val[x];
if (ch[x][0] && ch[x][1])
{
hmy[x]=max(hmy[ch[x][1]],val[x]+sum[ch[x][1]]+hmy[ch[x][0]]);
hmy[x]=max(hmy[x],val[x]+sum[ch[x][1]]);
ymh[x]=max(ymh[ch[x][0]],val[x]+sum[ch[x][0]]+ymh[ch[x][1]]);
ymh[x]=max(ymh[x],val[x]+sum[ch[x][0]]);
ans[x]=max(ans[ch[x][0]],ans[ch[x][1]]);
ans[x]=max(hmy[x],ans[x]);
ans[x]=max(ans[x],ymh[x]);
ans[x]=max(ans[x],ymh[ch[x][1]]+val[x]+hmy[ch[x][0]]);
ans[x]=max(ans[x],ymh[ch[x][1]]+val[x]);
ans[x]=max(ans[x],hmy[ch[x][0]]+val[x]);
}
else
{
if (ch[x][0])
{
hmy[x]=max(val[x],val[x]+hmy[ch[x][0]]);
ymh[x]=max(ymh[ch[x][0]],sum[ch[x][0]]+val[x]);
ans[x]=max(hmy[x],ymh[x]);
ans[x]=max(ans[x],ans[ch[x][0]]);
}
else
{
if (ch[x][1])
{
hmy[x]=max(hmy[ch[x][1]],sum[ch[x][1]]+val[x]);
ymh[x]=max(val[x],val[x]+ymh[ch[x][1]]);
ans[x]=max(hmy[x],ymh[x]);
ans[x]=max(ans[x],ans[ch[x][1]]);
}
else
{
hmy[x]=ymh[x]=ans[x]=val[x];
}
}
}
ans[x]=max(ans[x],val[x]);
}
int son(int x)
{
if (ch[fa[x]][0]==x) return 0;
else return 1;
}
void rotate(int x)
{
int y=fa[x],z=fa[y];
int b = son(x),c = son(y);
ch[z][c]=x;
fa[x]=z;
ch[y][b]=ch[x][!b];
fa[ch[x][!b]]=y;
ch[x][!b]=y;
fa[y]=x;
update(y);
update(x);
}
void splay(int x,int p)
{
while (fa[x]!=p)
{
int y = fa[x],z=fa[y];
int b = son(x),c = son(y);
if (z==p) rotate(x);
else
{
if (b==c)
{
rotate(y);
rotate(x);
}
else
{
rotate(x);
rotate(x);
}
}
}
if (p==0) root=x;
}
int kth(int x)
{
int now = root;
while (1)
{
//cerr<<now<<endl;
if (x<=siz[ch[now][0]]) now = ch[now][0];
else
{
if (x<=siz[ch[now][0]]+1) return now;
x-=siz[ch[now][0]]+1;
now = ch[now][1];
}
}
}
void insert(int pos,int x)
{
int qq = kth(pos+1);
int hj = kth(pos+2);
splay(qq,0);
splay(hj,qq);
int now = newnode(x);
ch[hj][0]=now;
fa[now]=hj;
splay(now,0);
}
void delet(int x)
{
int qq = kth(x);
int hj = kth(x+2);
//cout<<"*******"<<endl;
splay(qq,0);
splay(hj,qq);
delnode(ch[hj][0]);
ch[hj][0]=0;
update(hj);
splay(hj,0);
}
int build(int faa,int l,int r)
{
//cout<<l<<" "<<r<<endl;
if (l>r) return 0;
int mid = l+r >> 1;
int now = newnode(a[mid]);
fa[now] = faa;
ch[now][0] = build(now,l,mid-1);
ch[now][1] = build(now,mid+1,r);
update(now);
return now;
}
int main()
{
//freopen("lwk.in","r",stdin);
// freopen("a.out","w",stdout);
n=read();
a[0]=inf;
a[n+1]=inf;
for (int i=1;i<=n;i++) a[i]=read();
root = build(0,0,n+1);
//splay(root,0);
//cout<<ans[root]<<endl;
int q=read();
for (int i=1;i<=q;i++)
{
//cerr<<i<<endl;
char s[10];
scanf("%s",s+1);
if (s[1]=='I')
{
int x=read(),y=read();
x--;
insert(x,y);
}
if(s[1]=='D')
{
int x=read();
delet(x);
}
if (s[1]=='R')
{
int x=read(),y=read();
//splay(x,0);
int uu = kth(x+1);
splay(uu,0);
val[uu]=y;
update(uu);
}
if (s[1]=='Q')
{
int l=read(),r=read();
int qq = kth(l);
int hj = kth(r+2);
splay(qq,0);
splay(hj,qq);
cout<<ans[ch[hj][0]]<<"\n";
}
}
return 0;
}