您的位置:首页 > 其它

hdu 4699 Editor(Splay)

2013-09-02 01:22 337 查看
题意:对一个数列进行操作,光标位置后面插入一个权值为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
[2],pre
,sz
;

int key
,sum
,mx
,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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: