首页 > 其他 > 详细

[Splay]luogu P2596 书架

时间:2019-08-20 09:40:31      阅读:89      评论:0      收藏:0      [点我收藏+]

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

 

[Splay]luogu P2596 书架

原文:https://www.cnblogs.com/mastervan/p/11380837.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!