【BZOJ1861】【Zjoi2006】Book 书架 Splay

本文介绍了一种平衡树数据结构,并通过代码实例展示了如何在编程中使用该结构解决特定问题。其中包括数据结构的基本概念、代码实现、插入操作的重点解析及应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

链接:

#include <stdio.h>
int main()
{
    puts("转载请注明出处[vmurder]谢谢");
    puts("网址:blog.youkuaiyun.com/vmurder/article/details/45166317");
}

题解:

随便来一种数据结构就好啦。
这里写的是平衡树(一眼直接想到,而且发现很水)

注意。。

呃或许也不用太注意。
就是那个Insert操作要你干什么千万要看明白……

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 101000
#define ls son[x][0]
#define rs son[x][1]
#define is(x) (x==son[fa[x]][1])
#define inf 0x3f3f3f3f
using namespace std;
int src[N],n,m;
struct SPT
{
    int son[N][2],fa[N],root;
    int size[N],num[N];

    void pushup(int x)
    {
        size[x]=size[ls]+size[rs]+num[x];
    }
    void link(int x,int y,int d){son[y][d]=x,fa[x]=y;}
    void rotate(int x)
    {
        int y=fa[x],z=fa[y],i=is(x),t=son[x][!i];
        link(t,y,i),link(x,z,is(y)),link(y,x,!i);
        fa[0]=0,son[0][0]=son[0][1]=0;
        pushup(y);
    }
    void splay(int x,int d=0)
    {
        int y,z;
        while(fa[x]!=d)
        {
            y=fa[x],z=fa[y];
            if(z==d)rotate(x);
            else rotate(is(x)==is(y)?y:x),rotate(x);
        }
        pushup(x);
        if(!d)root=x;
    }
    int pred(int x)
    {
        splay(x);
        for(x=ls;rs;x=rs);
        return x;
    }
    int succ(int x)
    {
        splay(x);
        for(x=rs;ls;x=ls);
        return x;
    }
    int build(int L,int R)
    {
        int mid=L+R>>1,l=0,r=0;
        if(L<mid)l=build(L,mid-1);
        if(mid<R)r=build(mid+1,R);
        mid=src[mid],num[mid]=1;
        link(l,mid,0),link(r,mid,1);
        pushup(mid);
        return mid;
    }
    void init()
    {
        root=build(1,n);
        link(n+1,src[1],0),link(n+2,src[n],1);
    }
    void insert(int d,int x)
    {
        int suc=succ(d);
        splay(suc,d);
        link(x,suc,0);
        splay(x);
    }
    void remove(int x)
    {
        int pre=pred(x),suc=succ(x);
        splay(pre),splay(x,pre);
        link(rs,pre,1);
        splay(rs);
        ls=rs=0;
    }
    void Top(int x)
    {
        remove(x);
        insert(n+1,x);
    }
    void Bottom(int x)
    {
        remove(x);
        insert(pred(n+2),x);
    }
    void Insert(int x)
    {
        int t;scanf("%d",&t);
        if(t==0)return ;
        int pre=pred(x),suc=succ(x);
        remove(x);
        if(t==-1)insert(pred(pre),x);
        else insert(suc,x);
    }
    int Ask(int x)
    {
        splay(x);
        return size[ls];
    }
    int Query(int k)
    {
        int x=root;
        while(size[ls]+1!=k)
        {
            if(size[ls]>=k)x=ls;
            else k-=(size[ls]+1),x=rs;
        }
        return x;
    }
}spt;
char s[10];
int a,b;
int main()
{
    freopen("test.in","r",stdin);

    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d",&src[i]);
    spt.init();
    while(m--)
    {
        scanf("%s%d",s,&a);
        if(s[0]=='T')spt.Top(a);
        else if(s[0]=='B')spt.Bottom(a);
        else if(s[0]=='I')spt.Insert(a);
        else if(s[0]=='A')printf("%d\n",spt.Ask(a));
        else printf("%d\n",spt.Query(a));
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值