码迷,mamicode.com
首页 > 其他好文 > 详细

平衡树Splay

时间:2018-06-13 00:11:28      阅读:209      评论:0      收藏:0      [点我收藏+]

标签:for   大小   位置   顺序   \n   --   rank   ++   clu   

#include <cstdio>
#define ls t[now].ch[0]
#define rs t[now].ch[1]
int min(int x,int y){return x<y?x:y;}
int max(int x,int y){return x>y?x:y;}
const int inf=0x3f3f3f3f;
const int N=100010;
struct Splay
{
    int par,ch[2],dat,siz,cnt;
}t[N];
int tot=0,root,t_size=0;
int identity(int x)//是父亲的左0/右1孩子
{
    return t[t[x].par].ch[0]==x?0:1;
}
void connect(int fa,int s,int typ)//建立父子关系
{
    t[fa].ch[typ]=s;
    t[s].par=fa;
}
void updata(int now)
{
    t[now].siz=t[ls].siz+t[rs].siz+t[now].cnt;
}
void rotate(int p,int typ)//0左上旋,1右上旋
{
    int q=t[p].ch[typ];//要转的儿子
    connect(p,t[q].ch[typ^1],typ);//顺序不能换,得注意一下
    connect(t[p].par,q,identity(p));
    connect(q,p,typ^1);
    updata(p),updata(q);//顺序不能换
}
void splay(int v,int u)//把v位置调整至u
{
    u=t[u].par;
    while(t[v].par!=u)
    {
        int f=t[v].par,g=t[f].par;
        if(g==u||identity(v)!=identity(f))
            rotate(f,identity(v));
        else
        {
            rotate(g,identity(f));
            rotate(f,identity(v));
        }
    }
}
int New(int dat,int fa)
{
    t[++tot].par=fa,t[tot].dat=dat,t[tot].cnt=1,t[tot].siz=1,t_size++;
    return tot;
}
void free(int x)
{
    t[x].siz=0,t[x].dat=0,t[x].cnt=0,t[x].par=0,t[x].ch[0]=0,t[x].ch[1]=0;
    if(x==tot) tot--;
}
void insert(int dat)
{
    if(!t_size) {root=New(dat,0);connect(0,tot,1);return;}//特判建虚根
    int now=root,las;
    while(1)
    {
        int tpy=t[now].dat>dat?0:1;
        t[now].siz++;
        las=now;
        now=t[now].ch[tpy];
        if(!now)
        {
            now=New(dat,las);
            t[las].ch[tpy]=now;
            break;
        }
        if(t[now].dat==dat)
        {
            t[now].cnt++;
            break;
        }
    }
    splay(now,root);
    root=now;
}
int find(int dat)//查找并调整
{
    int now=root;
    while(1)
    {
        if(t[now].dat==dat)
        {
            splay(now,root);//调整位置至根
            root=now;
            return now;
        }
        int typ=t[now].dat>dat?0:1;
        now=t[now].ch[typ];
    }
}
int g_max(int now)
{
    return t[now].ch[1]?g_max(t[now].ch[1]):now;
}
void extrack(int dat)
{
    int loc=find(dat);//找到删除节点位置并伸展
    if(t[loc].cnt>1) {t[loc].cnt--;t[loc].siz--;return;}//删除一个值并更新
    t_size--;//整棵树的大小--
    if(!t[root].ch[0]) {root=t[root].ch[1];return;}//左子树空拿右子树顶
    loc=g_max(t[root].ch[0]);//找到左子树最大值的位置
    splay(loc,t[root].ch[0]);//把左子树最大值伸展至根节点
    connect(t[root].ch[0],t[root].ch[1],1);//建立联系
    loc=root;//记录一下原根以便free
    root=t[root].ch[0];//更新根节点
    connect(0,root,1);//与虚根建立关系
    updata(root);//更新大小
    free(loc);//释放原根
}
void get_rank(int x)//查询x的排名
{
    root=find(x);
    printf("%d\n",t[t[root].ch[0]].siz+1);
}
void fget_rank(int x)//排名为x的数
{
    int now=root;
    while(1)
    {
        if(t[ls].siz<x&&x<=t[ls].siz+t[now].cnt) {printf("%d\n",t[now].dat);return;}
        else if(x>t[ls].siz+t[now].cnt) {x-=t[ls].siz+t[now].cnt;now=rs;}
        else now=ls;
    }
}
void get_pre(int x)
{
    int m_max=-inf,now=root;
    while(now)
    {
        if(t[now].dat<x) {m_max=max(m_max,t[now].dat);now=rs;}
        else now=ls;
    }
    printf("%d\n",m_max);
}
void get_suc(int x)
{
    int m_min=inf,now=root;
    while(now)
    {
        if(t[now].dat>x) {m_min=min(m_min,t[now].dat);now=ls;}
        else now=rs;
    }
    printf("%d\n",m_min);
}
int main()
{
    int opt,x,n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&opt,&x);
        if(opt==1)
            insert(x);
        else if(opt==2)
            extrack(x);
        else if(opt==3)
            get_rank(x);//查询x的排名
        else if(opt==4)
            fget_rank(x);//查询排名为x的数
        else if(opt==5)
            get_pre(x);
        else
            get_suc(x);
    }
    return 0;
}

先放着...

平衡树Splay

标签:for   大小   位置   顺序   \n   --   rank   ++   clu   

原文地址:https://www.cnblogs.com/ppprseter/p/9175582.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!