题意:对一个数列进行操作,光标位置后面插入一个权值为x的数,删除光标前的那个数,光标左移一位,光标右移一位,求到k位置的最大的前缀和。
Splay在比赛的时候写得太Navie,T了整场。
左移和右移的操作就不说了,删除点的操作是,直接把第pos个点旋转成根结点,然后把这个点删除,将左右两个儿子(如果有)合并成一棵新的树。插入的时候,将pos个点旋转成根结点,然后在根和根的右儿子之间插入这个点。
同时维护sum(区间和),和mx(表示以x为根结点的最大前缀和),就可以解决这道题了。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define LL(x) (ch[x][0])
#define RR(x) (ch[x][1])
#define Kt(x) (ch[ ch[Rt][1] ][0])
#define INF (1<<30)
const int N=1e6+5;
struct SplayTree
{
int Rt,top;
int ch[N][2],pre[N],sz[N];
int key[N],sum[N],mx[N],pos;
void init()
{
top=Rt=pos=0;
pre[0]=LL(0)=RR(0)=sz[0]=0;
}
inline void Link(int x,int y,int f)
{
ch[y][f]=x; pre[x]=y;
}
inline void Rotate(int x,int f)
{
int y=pre[x],z=pre[y];
PushDown(y); PushDown(x);
Link(ch[x][f],y,!f);
Link(x,z,RR(z)==y);
Link(y,x,f);
PushUp(y);
}
inline void Splay(int x,int goal)
{
while(pre[x]!=goal)
{
int y=pre[x],z=pre[y];
int cx=(LL(y)==x),cy=(LL(z)==y);
if(z==goal) Rotate(x,cx);
else
{
if(cx==cy) Rotate(y,cy);
else Rotate(x,cx);
Rotate(x,cy);
}
}
PushUp(x);
if(goal==0) Rt=x;
}
inline void Select(int K,int goal)
{
int x=Rt;
PushDown(x);
while(1)
{
if(sz[LL(x)]>=K) x=LL(x);
else if(sz[LL(x)]+1==K) break;
else K-=sz[LL(x)]+1,x=RR(x);
PushDown(x);
}
Splay(x,goal);
}
inline int Join(int r1,int r2)
{
if(!r1)
{
if(!r2) return 0;
pre[r2]=0;
return r2;
}
int x=r1;
while(RR(x)) x=RR(x);
Splay(x,Rt);
Link(r2,x,1);
Rt=x; pre[x]=0;
PushUp(x);
return x;
}
void addNode(int valu,int &x,int f)
{
x=top++;
pre[x]=f; LL(x)=RR(x)=0;
key[x]=valu;
}
void PushDown(int x) {}
void PushUp(int x)
{
sz[x]=1; sum[x]=key[x];
if(LL(x)) sum[x]+=sum[LL(x)],sz[x]+=sz[LL(x)];
if(RR(x)) sum[x]+=sum[RR(x)],sz[x]+=sz[RR(x)];
if(LL(x))
{
mx[x]=max(mx[LL(x)],sum[LL(x)]+key[x]);
if(RR(x)) mx[x]=max(mx[x],sum[LL(x)]+key[x]+mx[RR(x)]);
}
else
{
mx[x]=key[x];
if(RR(x)) mx[x]=max(mx[x],key[x]+mx[RR(x)]);
}
}
inline void Insert()
{
int valu; scanf("%d",&valu);
int x=++top;
sz[x]=1; pre[x]=0; LL(x)=RR(x)=0;
key[x]=valu; sum[x]=0; mx[x]=-INF;
if(pos==0)
{
Link(Rt,x,1);
Rt=x; PushUp(Rt);
}
else
{
Select(pos,0);
int tmp=RR(Rt);
Link(x,Rt,1); Link(tmp,x,1);
PushUp(x); PushUp(Rt);
}
pos++;
}
inline void Delete()
{
if(pos==0) return;
Select(pos,0);
Rt=Join(LL(Rt),RR(Rt));
if(Rt) PushUp(Rt);
pos--;
}
void Query()
{
int K; scanf("%d",&K);
K=min(K,sz[Rt]);
Select(K,0);
int ans=-1;
if(LL(Rt)) ans=max(mx[LL(Rt)],sum[LL(Rt)]+key[Rt]);
else ans=key[Rt];
printf("%d\n",ans);
}
inline void shift(int flag)
{
if(flag==0)
{
if(pos>0) pos--;
}
else
{
if(pos<sz[Rt]) pos++;
}
}
void Debug(){ printf("Rt:%d\n",Rt); travel(Rt); }
void travel(int x)
{
if(x==0) return;
travel(LL(x));
printf("node:%d,pre:%d,sz:%d,lson:%d,rson:%d,key:%d,sum:%d,mx:%d\n",
x,pre[x],sz[x],LL(x),RR(x),key[x],sum[x],mx[x]);
travel(RR(x));
}
}spt;
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
spt.init();
for(int i=0;i<n;i++)
{
char op[100];
scanf("%s",op);
if(op[0]=='L') spt.shift(0);
else if(op[0]=='R') spt.shift(1);
else if(op[0]=='I') spt.Insert();
else if(op[0]=='D') spt.Delete();
else spt.Query();
// spt.Debug();
}
}
return 0;
}