[BZOJ 3224]普通平衡樹(忽然想要存個模板 Treap/Splay)

Description


您需要寫一種數據結構(可參考題目標題),來維護一些數,其中需要提供以下操作:
1. 插入x數
2. 刪除x數(若有多個相同的數,因只刪除一個)
3. 查詢x數的排名(若有多個相同的數,因輸出最小的排名)
4. 查詢排名爲x的數
5. 求x的前驅(前驅定義爲小於x,且最大的數)
6. 求x的後繼(後繼定義爲大於x,且最小的數)

Solution


其實差不多是黃學長那個板子

Treap

對了bzoj上似乎用srand(time(NUll))會RE

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<ctime>
using namespace std;
int size=0,root=0,ans;
struct Node
{
    int lch,rch;
    int val,size,rank,w;
}tree[100005];
void update(int k)
{
    tree[k].size=tree[tree[k].lch].size+tree[tree[k].rch].size+tree[k].w;
}
void leftRotate(int &k)
{
    int t=tree[k].rch;
    tree[k].rch=tree[t].lch;
    tree[t].lch=k;
    tree[t].size=tree[k].size;
    update(k);
    k=t;
}
void rightRotate(int &k)
{
    int t=tree[k].lch;
    tree[k].lch=tree[t].rch;
    tree[t].rch=k;
    tree[t].size=tree[k].size;
    update(k);
    k=t;
}
void _insert(int &k,int x)
{
    if(k==0)
    {
        size++;k=size;
        tree[k].size=tree[k].w=1;
        tree[k].rank=rand();
        tree[k].val=x;
        return;
    }
    tree[k].size++;
    if(x<tree[k].val)
    {
        _insert(tree[k].lch,x);
        if(tree[k].rank<tree[tree[k].lch].rank)rightRotate(k);
    }
    else if(x>tree[k].val)
    {
        _insert(tree[k].rch,x);
        if(tree[k].rank<tree[tree[k].rch].rank)leftRotate(k);
    }
    else if(tree[k].val==x)tree[k].w++;
}
void _delete(int &k,int x)
{
    if(k==0)return;
    if(tree[k].val==x)
    {
        if(tree[k].w>1)
        {
            tree[k].w--;tree[k].size--;return;
        }
        if(!tree[k].lch||!tree[k].rch)
        k=tree[k].lch+tree[k].rch;
        else if(tree[tree[k].lch].rank<tree[tree[k].rch].rank)
        {
            leftRotate(k);_delete(k,x);
        }
        else
        {
            rightRotate(k);_delete(k,x);
        }
    }
    else if(tree[k].val>x)
    {
        tree[k].size--;_delete(tree[k].lch,x);
    }
    else
    {
        tree[k].size--;_delete(tree[k].rch,x);
    }
}
int _queryRank(int k,int x)
{
    if(k==0)return 0;
    if(tree[k].val==x)return tree[tree[k].lch].size+1;
    if(tree[k].val<x)return tree[tree[k].lch].size+tree[k].w+_queryRank(tree[k].rch,x);
    else return _queryRank(tree[k].lch,x);
}
int _queryNum(int k,int x)
{
    if(k==0)return 0;
    if(x<=tree[tree[k].lch].size)return _queryNum(tree[k].lch,x);
    else if(x>tree[tree[k].lch].size+tree[k].w)
    {
        return _queryNum(tree[k].rch,x-tree[tree[k].lch].size-tree[k].w);
    }
    else return tree[k].val;
}
void _queryPre(int k,int x)
{
    if(k==0)return;
    if(tree[k].val<x)
    {
        ans=tree[k].val;
        _queryPre(tree[k].rch,x);
    }
    else _queryPre(tree[k].lch,x);
}
void _querySuc(int k,int x)
{
    if(k==0)return;
    if(tree[k].val>x)
    {
        ans=tree[k].val;
        _querySuc(tree[k].lch,x);
    }
    else _querySuc(tree[k].rch,x);
}
int main()
{    
    //srand(time(NULL));
    int n,opt,x;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&opt,&x);
        switch(opt)
        {
            case 1:_insert(root,x);break;
            case 2:_delete(root,x);break;
            case 3:cout<<_queryRank(root,x)<<endl;break;
            case 4:cout<<_queryNum(root,x)<<endl;break;
            case 5:ans=0;_queryPre(root,x);cout<<ans<<endl;break;
            case 6:ans=0;_querySuc(root,x);cout<<ans<<endl;break;
        }
    }
    return 0; 
}

Splay(Update)

bzoj這道用cin.cout也會RE啊QvQ

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
int root=0,siz=0,ans;
struct Node{
    int ch[2],father;
    int siz,val,w;
}tr[100005];
int read()
{
    int f=1,x=0;
    char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-')f=-1;c=getchar();
    }
    while(c>='0'&&c<='9'){
        x=x*10+c-'0';c=getchar();
    }
    return x*f;
}
void update(int k)
{
    tr[k].siz=tr[tr[k].ch[0]].siz+tr[tr[k].ch[1]].siz+tr[k].w;
}
void rotate(int x,int &k)
{
    int y=tr[x].father;
    int z=tr[y].father;
    int t=(tr[y].ch[0]==x)?0:1;
    if(y==k)k=x;
    else
    {
        if(tr[z].ch[0]==y)tr[z].ch[0]=x;
        else tr[z].ch[1]=x;
    }
    tr[x].father=z;tr[y].father=x;
    tr[tr[x].ch[t^1]].father=y;
    tr[y].ch[t]=tr[x].ch[t^1];
    tr[x].ch[t^1]=y;
    update(y);update(x);
}
void splay(int x,int &k)
{
    int y,z;
    while(x!=k)
    {
        y=tr[x].father;z=tr[y].father;
        if(y!=k)
        {
            if((tr[y].ch[0]==x)^(tr[z].ch[1]==y))
            rotate(x,k);
            else rotate(y,k);
        }
        rotate(x,k);
    }
}
void _insert(int &k,int x,int f)
{
    if(!k)
    {
        siz++;k=siz;
        tr[k].father=f;
        tr[k].val=x;
        tr[k].siz=tr[k].w=1;
        tr[k].ch[0]=tr[k].ch[1]=0;
        splay(k,root);
        return;
    }
    tr[k].siz++;
    if(x==tr[k].val)tr[k].w++;
    else if(x>tr[k].val)_insert(tr[k].ch[1],x,k);
    else _insert(tr[k].ch[0],x,k);
}
void _delete(int k,int x)
{
    if(!k)return;
    if(tr[k].val==x)
    {
        splay(k,root);
        if(tr[k].w>1)
        {
            tr[k].w--;tr[k].siz--;
            return;
        }
        if(tr[k].ch[0]==0||tr[k].ch[1]==0)
        {
            root=tr[k].ch[0]+tr[k].ch[1];
            tr[root].father=0;
            return;
        }
        int t=tr[k].ch[1];
        while(tr[t].ch[0])t=tr[t].ch[0];
        tr[t].ch[0]=tr[k].ch[0];
        tr[tr[k].ch[0]].father=t;
        root=tr[k].ch[1];
        tr[root].father=0;
        while(t!=root)update(t),t=tr[t].father;
        update(root);
        return;
    }
    tr[k].siz--;
    if(tr[k].val>x)_delete(tr[k].ch[0],x);
    else _delete(tr[k].ch[1],x);
}
int _queryRank(int k,int x)
{
    if(!k)return 0;
    if(tr[k].val==x)return tr[tr[k].ch[0]].siz+1;
    if(tr[k].val<x)return tr[tr[k].ch[0]].siz+tr[k].w+_queryRank(tr[k].ch[1],x);
    else return _queryRank(tr[k].ch[0],x);
}
int _queryNum(int k,int x)
{
    if(!k)return 0;
    if(x<=tr[tr[k].ch[0]].siz)return _queryNum(tr[k].ch[0],x);
    else if(x>tr[tr[k].ch[0]].siz+tr[k].w)
    {
        return _queryNum(tr[k].ch[1],x-tr[tr[k].ch[0]].siz-tr[k].w);
    }
    else return tr[k].val;
}
void _queryPre(int k,int x)
{
    if(!k)return;
    if(tr[k].val<x)
    {
        ans=tr[k].val;
        _queryPre(tr[k].ch[1],x);
    }
    else _queryPre(tr[k].ch[0],x);
}
void _querySuc(int k,int x)
{
    if(!k)return;
    if(tr[k].val>x)
    {
        ans=tr[k].val;
        _querySuc(tr[k].ch[0],x);
    }
    else _querySuc(tr[k].ch[1],x);
}
int main()
{
    int n,opt,x;
    n=read();
    for(int i=1;i<=n;i++)
    {
        opt=read();x=read();
        switch(opt)
        {
            case 1:_insert(root,x,0);break;
            case 2:_delete(root,x);break;
            case 3:printf("%d\n",_queryRank(root,x));break;
            case 4:printf("%d\n",_queryNum(root,x));break;
            case 5:ans=0;_queryPre(root,x);printf("%d\n",ans);break;
            case 6:ans=0;_querySuc(root,x);printf("%d\n",ans);break;
        }
    }
    return 0;
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章