[模板]普通平衡树

Posted Excim

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[模板]普通平衡树相关的知识,希望对你有一定的参考价值。

原题链接:https://www.luogu.org/problemnew/show/3369

一个平衡树的板子

代码来自于黄学长,个人码风

#include<cstdio>
#include<cstdlib>
#include<iostream>
using namespace std;
void read(int &y)
{
    y=0;char x=getchar();
    while(x<0||x>9) x=getchar();
    while(x>=0&&x<=9)
    {
        y=y*10+x-0;
        x=getchar();
    }
}
struct treap
{
    int l,r,v,size,rnd,w;
}tr[100005];
int n,cnt,rot,op,m,ans;
void update(int k)
{
    tr[k].size=tr[tr[k].l].size+tr[tr[k].r].size+tr[k].w;
}
void rturn(int &k)
{
    int t=tr[k].l;
    tr[k].l=tr[t].r;tr[t].r=k;
    tr[t].size=tr[k].size;
    update(k);k=t;
}
void lturn(int &k)
{
    int t=tr[k].r;
    tr[k].r=tr[t].l;tr[t].l=k;
    tr[t].size=tr[k].size;
    update(k);k=t;
}
void insert(int &k,int x)
{
    if(k==0)
    {
        cnt++;k=cnt;
        tr[k].size=tr[k].w=1;
        tr[k].v=x;tr[k].rnd=rand();
        return;
    }
    tr[k].size++;
    if(tr[k].v==x) tr[k].w++;
    else if(x>tr[k].v)
    {
        insert(tr[k].r,x);
        if(tr[tr[k].r].rnd<tr[k].rnd) lturn(k);
    }
    else
    {
        insert(tr[k].l,x);
        if(tr[tr[k].l].rnd<tr[k].rnd) rturn(k);
    }
}
void del(int &k,int x)
{
    if(k==0) return;
    if(tr[k].v==x)
    {
        if(tr[k].w>1)
        {
            tr[k].w--;
            tr[k].size--;
            return;
        }
        if(tr[k].l*tr[k].r==0) k=tr[k].l+tr[k].r;
        else if(tr[tr[k].l].rnd<tr[tr[k].r].rnd)
        {
            rturn(k);
            del(k,x);
        }
        else
        {
            lturn(k);
            del(k,x);
        }
    }
    else if(x>tr[k].v)
    {
        tr[k].size--;
        del(tr[k].r,x);
    }
    else
    {
        tr[k].size--;
        del(tr[k].l,x);
    }
}
int rank(int k,int x)
{
    if(k==0) return 0;
    if(tr[k].v==x) return tr[tr[k].l].size+1;
    else if(x>tr[k].v) return tr[tr[k].l].size+tr[k].w+rank(tr[k].r,x);
    else return rank(tr[k].l,x);
}
int num(int k,int x)
{
    if(k==0) return 0;
    if(x<=tr[tr[k].l].size) return num(tr[k].l,x);
    else if(x>tr[tr[k].l].size+tr[k].w) return num(tr[k].r,x-tr[tr[k].l].size-tr[k].w);
    else return tr[k].v;
}
void pro(int k,int x)
{
    if(k==0) return;
    if(tr[k].v<x)
    {
        ans=k;
        pro(tr[k].r,x);
    } 
    else pro(tr[k].l,x);
}
void sub(int k,int x)
{
    if(k==0) return;
    if(tr[k].v>x)
    {
        ans=k;
        sub(tr[k].l,x);
    }
    else sub(tr[k].r,x);
}
int main()
{
    read(n);
    while(n--)
    {
        scanf("%d %d",&op,&m);
        if(op==1) insert(rot,m);
        if(op==2) del(rot,m);
        if(op==3) printf("%d\n",rank(rot,m));
        if(op==4) printf("%d\n",num(rot,m));
        if(op==5)
        {
            ans=0;
            pro(rot,m);
            printf("%d\n",tr[ans].v);
        }
        if(op==6)
        {
            ans=0;
            sub(rot,m);
            printf("%d\n",tr[ans].v);
        }
    }
    return 0;
}

 

以上是关于[模板]普通平衡树的主要内容,如果未能解决你的问题,请参考以下文章

Luogu P3369 模板普通平衡树

P3369 模板普通平衡树 题解(Splay)

模板普通平衡树

BZOJ 3223 普通平衡树 | 平衡树模板

LG3369 模板普通平衡树

题解 P3369 模板普通平衡树(Treap/SBT)