Treap模板

摘自 Hallmeow

支持以下操作:

1.插入x数

2. 删除x数(若有多个相同的数,因只删除一个)

3. 查询x数的排名(若有多个相同的数,因输出最小的排名)

4. 查询排名为x的数

5. 求x的前驱(前驱定义为小于x,且最大的数)

6. 求x的后继(后继定义为大于x,且最小的数)

#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
#define pos(i,a,b) for(int i=(a);i<=(b);i++)
#define pos2(i,a,b) for(int i=(a);i>=(b);i--)
#define N 500010
struct Treap
{
       int l,r,w,v,size,rnd;
       //v为实际数值;rnd为优先级;size为以它为根的子树大小;w为自身节点存的数的个数(数据可以有多个重复的数)
}tree[N];
int n;
int root,size;
void update(int k)
{
     tree[k].size=tree[tree[k].l].size+tree[tree[k].r].size+tree[k].w;
     //更新子树大小
}
void rturn(int &k)
{
     int t=tree[k].l;
     tree[k].l=tree[t].r;
     tree[t].r=k;
     tree[t].size=tree[k].size;
     update(k);
     k=t;
}//右旋转
void lturn(int &k)
{
     int t=tree[k].r;
     tree[k].r=tree[t].l;
     tree[t].l=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].w=tree[k].size=1;
       tree[k].v=x;
       tree[k].rnd=rand();//随机数
       return;
    }
    tree[k].size++;
    if(tree[k].v==x)//如果有多个,w++
       tree[k].w++;
    else
    {
        if(tree[k].v<x)//满足二叉排序树性质
        {
           insert(tree[k].r,x);
           if(tree[tree[k].r].rnd<tree[k].rnd)
              lturn(k);//维护堆性质,左旋转
        }
        else
        {
            insert(tree[k].l,x);
            if(tree[tree[k].l].rnd<tree[k].rnd)
              rturn(k);
        }
    }
}
int tmp;
void query_pro(int k,int x)
{
    if(k==0)
      return;
    if(x>tree[k].v)
    {
       tmp=k;//不断更新过程。数值小于目标值,去右子树里找 ,找到第一个比它大的值。此时更新结果即为比它小的最大的值
       query_pro(tree[k].r,x);
    }
    else
      query_pro(tree[k].l,x);
}
void query_sub(int k,int x)
{
     if(k==0)
      return;
     if(x<tree[k].v)//与上面同理
     {
       tmp=k;
       query_sub(tree[k].l,x);
     }
     else
      query_sub(tree[k].r,x);
}
void del(int &k,int x)
{
     if(k==0)
       return;
     if(tree[k].v==x)
     {
        if(tree[k].w>1)//若不止相同值的个数有多个,删去一个
        {
          tree[k].w--;
          tree[k].size--;
          return;
        }
        if(tree[k].l*tree[k].r==0)//有一个儿子为空
          k=tree[k].l+tree[k].r;
        else
        {
            if(tree[tree[k].l].rnd<tree[k].rnd)
            {
               rturn(k);
               del(k,x);
            }
            else
            {
                lturn(k);
                del(k,x);
            }
        }
     }
     else
     {
         if(x>tree[k].v)
         {
            tree[k].size--;
            del(tree[k].r,x);
         }
         else
         {
             tree[k].size--;
             del(tree[k].l,x);
         }
     }
}
int query_rank(int k,int x)
{
    if(k==0)
      return 0;
    if(tree[k].v==x)
     return tree[tree[k].l].size+1;//找到目标值,左子树都比它小,左子树大小+1即为它的排名
    else
    {
        if(x>tree[k].v)
          return tree[tree[k].l].size+tree[k].w+query_rank(tree[k].r,x);
        else
          return query_rank(tree[k].l,x);
    }
}
int query_num(int k,int x)
{
    if(k==0)
      return 0;
    if(x<=tree[tree[k].l].size)
      return query_num(tree[k].l,x);
    else
      if(x>tree[tree[k].l].size+tree[k].w)
        return query_num(tree[k].r,x-tree[tree[k].l].size-tree[k].w);
      else
        return tree[k].v;
}
int main()
{
    //freopen("phs.in","r",stdin);
    //freopen("phs.out","w",stdout);
    scanf("%d",&n);
    int opt,x;
    pos(i,1,n)
    {
        scanf("%d%d",&opt,&x);
        switch(opt)
        {
        case 1:insert(root,x);break;
        case 2:del(root,x);break;
        case 3:printf("%d\n",query_rank(root,x));break;
        case 4:printf("%d\n",query_num(root,x));break;
        case 5:tmp=0;query_pro(root,x);printf("%d\n",tree[tmp].v);break;
        case 6:tmp=0;query_sub(root,x);printf("%d\n",tree[tmp].v);break;
        }
    }
    //while(1);
    return 0;
}

Splay指针版:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<set>
#include<map>
#include<queue>
#include<algorithm>
#include<vector>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<stack>
#define INF 2100000000
#define ll long long
#define clr(x)  memset(x,0,sizeof(x))
#define maxclr(x)  memset(x,127,sizeof(x))

using namespace std;

inline int read()
{
    char c;
    int ret=0,b=1;
    while(!(c>='0'&&c<='9'))
    {
        if(c=='-')b=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9')
    {
        ret=(c-'0')+(ret<<1)+(ret<<3);
        c=getchar();
    }
    return ret*b;
}

#define M 100005

struct tree2
{
    tree2 *son[2],*fa;
    int n,siz,num;
}*root,dizhi[M],*null,*Null;

#define lson son[0]
#define rson son[1]

int n,t;

tree2 *newtree(tree2 *fa,int x)
{
    tree2 *tree=&dizhi[t++];
    tree->siz=tree->num=1;
    tree->lson=tree->rson=Null;
    tree->n=x;
    tree->fa=fa;
    return tree;
}

void pushup(tree2 *tree)
{
    if(tree==null)return ;
    tree->siz=tree->num+tree->lson->siz+tree->rson->siz;
}

void rotate(tree2 *tree,int x)
{
    tree2 *fa=tree->fa;
    fa->son[x^1]=tree->son[x];
    if(tree->son[x]!=Null)tree->son[x]->fa=fa;
    fa->fa->son[fa->fa->son[1]==fa]=tree;
    tree->fa=fa->fa;
    fa->fa=tree;
    tree->son[x]=fa;
    pushup(fa);
}

void splay(tree2 *tree,tree2 *goal)
{
    if(tree==goal)return ;
    while(tree->fa!=goal)
    {
        tree2 *fa=tree->fa,*gfa=fa->fa;
        if(gfa==goal)
        {
            rotate(tree,fa->son[0]==tree);
            break;
        }
        int x=gfa->son[1]==fa;
        if((fa->son[1]==tree)==x)
        {
            rotate(fa,x^1);
            rotate(tree,x^1);
        }
        else
        {
            rotate(tree,x);
            rotate(tree,x^1);
        }
    }
    pushup(tree);
    if(goal==null)root=tree;
}

void insert(int k)
{
    if(root==NULL)
    {
        root=newtree(null,k);
        return ;
    }
    tree2 *temp=root;
    while(temp->son[temp->n<k]!=Null)
    {
        if(temp->n==k)break;
        temp=temp->son[temp->n<k];
    }
    if(temp->n==k)
    {
        temp->siz++;
        temp->num++;
        splay(temp,null);
        return;
    }
    temp->son[temp->n<k]=newtree(temp,k);
    splay(temp->son[temp->n<k],null);
}

tree2 *find(int k)
{
    tree2 *temp=root;
    while(temp->son[temp->n<k])
    {
        if(temp->n==k)break;
        temp=temp->son[temp->n<k];
    }
    return temp;
}

void dele(int k)
{
    tree2 *temp=find(k);
    if(temp->num!=1)
    {
        temp->siz--;
        temp->num--;
        splay(temp,null);
        return ;
    }
    int x=temp->fa->son[1]==temp;
    if(temp->lson==Null)
        if(temp->rson==Null)
            temp->fa->son[x]=Null;
        else 
        {
            temp->fa->son[x]=temp->rson;
            temp->rson->fa=temp->fa;
        }
    else
        if(temp->rson==Null)
        {
            temp->fa->son[x]=temp->lson;
            temp->lson->fa=temp->fa;
        }
        else
        {
            tree2 *tree=temp->lson;
            temp->fa->son[x]=temp->lson;
            temp->lson->fa=temp->fa;
            while(tree->rson!=Null)tree=tree->rson;
            tree->rson=temp->rson;
            temp->rson->fa=tree;
            pushup(tree);
            splay(tree,null);
            return ;
        }
    pushup(temp->fa);
    splay(temp->fa,null);
}

int query(int k)
{
    tree2 *temp=root;
    int num=0;
    while(temp->n!=k)
    {
        int x=temp->n<k;
        if(x==1)num+=temp->lson->siz+temp->num;
        temp=temp->son[x];
    }
    num+=temp->lson->siz;
    splay(temp,null);
    return num+1;
}

int query_rank(int k)
{
    tree2 *temp=root;
    int num=temp->lson->siz;
    while(!(k>num&&k<=num+temp->num))
    {
        if(k>num)
        {
            k-=num+temp->num;
            temp=temp->rson;
        }
        else temp=temp->lson;
        num=temp->lson->siz;
    }
    splay(temp,null);
    return temp->n;
}

int get_pre(int k)
{
    tree2 *tree=root;
    int ret=0;
    while(tree->lson!=Null||tree->rson!=Null)
    {
        if(tree->n>=k)
            if(tree->lson!=Null)tree=tree->lson;
            else break;
        else
        {
            ret=max(ret,tree->n);
            if(tree->rson!=Null)tree=tree->rson;
            else break;
        }
    }
    if(tree->n<k)ret=max(ret,tree->n);
    splay(tree,null);
    return ret;
}

int get_next(int k)
{
    tree2 *tree=root;
    int ret=INF;
    while(tree->lson!=Null||tree->rson!=Null)
    {
        if(tree->n<=k)
            if(tree->rson!=Null)tree=tree->rson;
            else break;
        else
        {
            ret=min(ret,tree->n);
            if(tree->lson!=Null)tree=tree->lson;
            else break;
        }
    }
    if(tree->n>k)ret=min(ret,tree->n);
    splay(tree,null);
    return ret;
}

int main()
{
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    n=read();
    Null=&dizhi[t++];null=&dizhi[t++];
    for(int i=1;i<=n;i++)
    {
        int c=read(),x=read();
        switch(c)
        {
            case 1:insert(x);break;
            case 2:dele(x);break;
            case 3:printf("%d\n",query(x));break;
            case 4:printf("%d\n",query_rank(x));break;
            case 5:printf("%d\n",get_pre(x));break;
            case 6:printf("%d\n",get_next(x));break;
        }
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值