[Splay]luogu P2596 书架

https://www.luogu.org/problem/P2596

分析

?我怎么又开始写水题了

拿一个rev数组记录编号为s的书对应Splay中哪个节点

然后top就是将对应点旋至根,将左儿子嫁接到其后继上

bottom类似

insert操作只需要直接交换节点与其前驱/后继的信息以及rev值

ask将s旋到根输出左儿子大小即可

query直接Get_Kth

 

#include <iostream> 
#include <cstdio>
using namespace std;
const int N=8e4+10;
struct Node {
    int c[2],sz,id,f;
}t[N];
int rt,cnt;
int n,m,rev[N];

void Update(int x) {t[x].sz=t[t[x].c[0]].sz+t[t[x].c[1]].sz+1;}

bool Witch(int x) {return t[t[x].f].c[1]==x;}

void Rotate(int x) {
    int f=t[x].f,gf=t[f].f,lr=Witch(x);
    t[x].f=gf;if (gf) t[gf].c[Witch(f)]=x;
    t[f].c[lr]=t[x].c[lr^1];if (t[x].c[lr^1]) t[t[x].c[lr^1]].f=f;
    t[t[f].f=x].c[lr^1]=f;
    Update(f);Update(x);
}

void Splay(int x) {
    for (int f=t[x].f;f;Rotate(x),f=t[x].f)
        if (t[f].f) Rotate(Witch(x)==Witch(f)?f:x);
    rt=x;
}

int Get_Kth(int x,int k) {
    if (t[t[x].c[0]].sz+1>k) return Get_Kth(t[x].c[0],k);
    if (t[t[x].c[0]].sz+1==k) return x;
    return Get_Kth(t[x].c[1],k-t[t[x].c[0]].sz-1);
}

void Add(int val) {
    t[++cnt]=(Node){0,0,1,val,0};rev[val]=cnt;
    if (cnt<2) {
        rt=cnt;
        return;
    }
    t[t[cnt-1].c[1]=cnt].f=cnt-1;Update(cnt-1);
    Splay(cnt);
}

void Swap(int x,int type) {
    if (type==0) return;
    Splay(x);
    int y;
    if (type==-1) {
        y=t[x].c[0];
        if (!y) return;
        while (t[y].c[1]) y=t[y].c[1];
    }
    else {
        y=t[x].c[1];
        if (!y) return;
        while (t[y].c[0]) y=t[y].c[0];
    }
    swap(t[x].id,t[y].id);swap(rev[t[x].id],rev[t[y].id]);
}

void Top(int x) {
    Splay(x);
    if (!t[x].c[0]) return;
    int y=t[x].c[1];
    if (!y) {
        t[x].c[1]=t[x].c[0];t[x].c[0]=0;
        return;
    }
    while (t[y].c[0]) y=t[y].c[0];
    t[t[y].c[0]=t[x].c[0]].f=y;t[x].c[0]=0;
    Splay(y);
}

void Bottom(int x) {
    Splay(x);
    if (!t[x].c[1]) return;
    int y=t[x].c[0];
    if (!y) {
        t[x].c[0]=t[x].c[1];t[x].c[1]=0;
        return;
    }
    while (t[y].c[1]) y=t[y].c[1];
    t[t[y].c[1]=t[x].c[1]].f=y;t[x].c[1]=0;
    Splay(y);
}

int main() {
    scanf("%d%d",&n,&m);
    for (int i=1,a;i<=n;i++) scanf("%d",&a),Add(a);
    for (int i=1;i<=m;i++) {
        char c[10];int x,y;
        scanf("%s%d",c+1,&x);
        if (c[1]=='T') Top(rev[x]);
        if (c[1]=='B') Bottom(rev[x]);
        if (c[1]=='I') {
            scanf("%d",&y);
            Swap(rev[x],y);
        }
        if (c[1]=='A') Splay(rev[x]),printf("%d\n",t[t[rev[x]].c[0]].sz);
        if (c[1]=='Q') printf("%d\n",t[Get_Kth(rt,x)].id);
    }
}
View Code

 

posted @ 2019-08-20 07:44  Vagari  阅读(176)  评论(0编辑  收藏  举报