洛谷P2596 [ZJOI2006]书架(BZOJ1861)

来源:互联网 发布:fcn网络结构 编辑:程序博客网 时间:2024/05/21 22:55

平衡树

洛谷题目传送门
BZOJ题目传送门

初始想法:

对于每个节点,新增一个变量表示当前节点的优先级,用Splay维护。
置顶/置底时先把节点取出,把优先级修改到最大/最小,再插入。
放回时把两个节点取出,交换优先级后插入。
询问的话直接做就好了。

然而打了一个下午没打出来。。。实在太烦了。。。
这时候ZZK飘了过来,看了一眼:“这不是平衡树维护序列裸题吗”
Orz

正解:

Top:把x Splay到根,然后把x的左子树合并到x的后继上。
Bottom:把x Splay到根,然后把x的右子树合并到x的前驱上。
Insert:直接交换x与其前驱/后继的信息。
Ask:把x Splay到根,答案就是它的子树大小。
Query:直接找就好了。

代码:

#include<cstdio>#include<cstring>#include<algorithm>#define N 80000using namespace std;struct node{    int w,size,to[2],fa;}t[N*2+5];int n,m,rt,nd,id[N+5],num[N+5];char s[10];void updt(int x){    t[x].size=t[t[x].to[0]].size+t[t[x].to[1]].size+1;    id[num[t[x].to[0]]]=t[x].to[0],id[num[t[x].to[1]]]=t[x].to[1];}void rtt(int x,int &w){    int y=t[x].fa,z=t[y].fa,p=(t[y].to[0]!=x);    if (y==w) w=x;    else t[z].to[(t[z].to[0]!=y)]=x;    t[x].fa=z,t[y].fa=x,t[t[x].to[p^1]].fa=y;    t[y].to[p]=t[x].to[p^1],t[x].to[p^1]=y;    updt(y),updt(x);}void splay(int x,int &w){    while (x!=w){        int y=t[x].fa,z=t[y].fa;        if (y!=w)            if ((t[y].to[0]==x)^(t[z].to[0]==y)) rtt(x,w);            else rtt(y,w);        rtt(x,w);    }    id[num[x]]=x;}void nsrt(int x){    num[++nd]=x,t[nd].size=1,id[x]=nd,t[nd].to[0]=t[nd].to[1]=0;    if (nd>1) t[nd-1].to[1]=nd,t[nd].fa=nd-1,splay(nd,rt);}int srch(int x,int w){    int p=t[x].to[0];    if (t[p].size+1==w) return x;    if (t[p].size>=w) return srch(p,w);    return srch(t[x].to[1],w-t[p].size-1);}void tp(int x){    x=id[x],splay(x,rt);    if (!t[x].to[0]) return;    if (!t[x].to[1]) t[x].to[1]=t[x].to[0],t[x].to[0]=0;    else{        int p=srch(rt,t[t[x].to[0]].size+2);        t[t[rt].to[0]].fa=p,t[p].to[0]=t[rt].to[0];        t[rt].to[0]=0,splay(p,rt);    }}void bttm(int x){    x=id[x],splay(x,rt);    if (!t[x].to[1]) return;    if (!t[x].to[0]) t[x].to[0]=t[x].to[1],t[x].to[1]=0;    else{        int p=srch(rt,t[t[x].to[0]].size);        t[t[rt].to[1]].fa=p,t[p].to[1]=t[rt].to[1];        t[rt].to[1]=0,splay(p,rt);    }}void ns(int x,int w){    if (!w) return; splay(id[x],rt); w++;    int p=srch(rt,t[t[id[x]].to[0]].size+w);    int x1=num[p],x2=id[x];    swap(id[x],id[x1]);    swap(num[x2],num[p]);}int main(){    scanf("%d%d",&n,&m); rt=1;    for (int x,i=1;i<=n;i++)        scanf("%d",&x),nsrt(x);    for (int x,p,i=1;i<=m;i++){        scanf("%s%d",s,&x);        switch (s[0]){            case 'T': tp(x); break;            case 'B': bttm(x); break;            case 'I': scanf("%d",&p),ns(x,p); break;            case 'A': x=id[x],splay(x,rt),printf("%d\n",t[t[x].to[0]].size); break;            case 'Q': printf("%d\n",num[srch(rt,x)]); break;        }    }    return 0;}
原创粉丝点击