【bzoj3224】Tyvj 1728 普通平衡树

6 篇文章 0 订阅

Description

您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)

Input

第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)

Output

对于操作3,4,5,6每行输出一个数,表示对应答案

Sample Input

10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
Sample Output

106465
84185
492737

代码(splay)

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
int c[1000005][2],fa[1000005],size[1000005],num[2000005];
int cnt,n,rt,ans;

inline int read()
{
    int x=0,f=1;char ch=getchar();
    while (ch<'0'||ch>'9'){if (ch=='-') f=-1; ch=getchar();}
    while (ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}

inline void update(int x)
{
    int l=c[x][0],r=c[x][1];
    size[x]=size[l]+size[r]+1;
}

using namespace std;

void rotate(int x,int &k)
{
    int l,r,y=fa[x],z=fa[y];
    if (c[y][0]==x) l=0;else l=1;r=l^1;
    if (y==k) k=x;
    else if (c[z][0]==y) c[z][0]=x;else c[z][1]=x;
    fa[x]=z;fa[y]=x;
    fa[c[x][r]]=y;c[y][l]=c[x][r];
    c[x][r]=y;
    update(y);update(x);
}

void splay(int x,int &k)
{
    int y,z;
    while (x!=k)
    {
        y=fa[x];z=fa[y];
        if (y!=k)
        {
            if (c[z][0]==y^c[y][0]==x) rotate(x,k);else rotate(y,k);
        }
        rotate(x,k);
    }
}

void insert(int &k,int x,int f)
{
    if (k==0){k=++cnt;num[k]=x;fa[k]=f;size[k]=1;splay(k,rt);return;}
    if (x>=num[k]) insert(c[k][1],x,k);else insert(c[k][0],x,k);
}

void find(int k,int x)
{
    if (k==0) return;
    if (num[k]==x){ans=k;find(c[k][0],x);return;}
    if (num[k]>x) find(c[k][0],x);else find(c[k][1],x);
}

void query_before(int k,int x)
{
    if (k==0) return;
    if (num[k]<x) {ans=k;query_before(c[k][1],x);}
    else query_before(c[k][0],x);
}

void query_after(int k,int x)
{
    if (k==0) return;
    if (num[k]>x) {ans=k;query_after(c[k][0],x);}
    else query_after(c[k][1],x);    
}

void cl(int &x)
{   
    if (c[x][0]) cl(c[x][0]);
    else if (c[x][1]) cl(c[x][1]);
    else ans=fa[x],x=0;
}

void del(int x)
{
    ans=0;
    query_before(rt,x);
    int x1=ans;
    ans=0;
    query_after(rt,x);
    int x2=ans;
    splay(x1,rt);splay(x2,c[rt][1]);
    cl(x2);
    splay(ans,rt);
}

int query_rank(int x)
{
    ans=0;
    find(rt,x);
    x=ans;
    if (x!=0) splay(x,rt);
    return size[c[x][0]];
}

int query_num(int k,int x)
{
    int l=c[k][0],r=c[k][1];
    if (size[l]+1==x) return k;
    if (size[l]>=x) return query_num(l,x);else return query_num(r,x-size[l]-1);
}

int main()
{
    n=read();
    int opt,x;
    insert(rt,-2000000001,0);
    insert(rt,2000000001,0);
    while (n--)
    {
        opt=read();x=read();
        if (opt==1) insert(rt,x,0);
        if (opt==2) del(x);
        if (opt==3) printf("%d\n",query_rank(x));
        if (opt==4) printf("%d\n",num[query_num(rt,x+1)]);
        if (opt==5) 
        {
            query_before(rt,x);
            printf("%d\n",num[ans]);
        }
        if (opt==6) 
        {
            query_after(rt,x);
            printf("%d\n",num[ans]);
        }
    }
    return 0;
}

代码(treap)

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#define N 1000005
int n,cnt,rt,ans;
int size[N],sum[N],rnd[N],num[N],ls[N],rs[N];
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while (ch<'0'||ch>'9'){if (ch=='-') f=-1; ch=getchar();}
    while (ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
inline void update(int k)
{
    size[k]=size[ls[k]]+size[rs[k]]+sum[k];
}
inline void lturn(int &k)
{
    int t=rs[k];rs[k]=ls[t];ls[t]=k;
    size[t]=size[k];update(k);k=t;
}
inline void rturn(int &k)
{
    int t=ls[k];ls[k]=rs[t];rs[t]=k;
    size[t]=size[k];update(k);k=t;
}
using namespace std;
void insert(int &k,int x)
{
    if (k==0){k=++cnt;size[k]=1;num[k]=x;sum[k]=1;rnd[k]=rand();return;}
    size[k]++;
    if (num[k]==x)sum[k]++;
    else if (x>num[k])
    {
        insert(rs[k],x);
        if (rnd[rs[k]]<rnd[k])lturn(k);
    }
    else
    {
        insert(ls[k],x);
        if (rnd[ls[k]]<rnd[k])rturn(k);
    }
}
void del(int &k,int x)
{
    if (k==0) return;
    if (num[k]==x)
    {
        if (sum[k]>1)
        {
            sum[k]--;size[k]--;return;
        }
        if (rs[k]*ls[k]==0) k=rs[k]+ls[k];
        else if (rnd[ls[k]]<rnd[rs[k]])
            rturn(k),del(k,x);
        else lturn(k),del(k,x);
    }
    else if (x>num[k]) 
        size[k]--,del(rs[k],x);
    else size[k]--,del(ls[k],x);
}
int query_rank(int k,int x)
{
    if (k==0) return 0;
    if (num[k]==x) return size[ls[k]]+1;
    else if (x>num[k])
        return size[ls[k]]+sum[k]+query_rank(rs[k],x);
    else return query_rank(ls[k],x);
}
int query_num(int k,int x)
{
    if (k==0) return 0;
    if (x<=size[ls[k]]) return query_num(ls[k],x);
    else if (x>size[ls[k]]+sum[k]) 
        return query_num(rs[k],x-size[ls[k]]-sum[k]);
    else return num[k];
}
void query_pro(int k,int x)
{
    if (k==0) return;
    if (num[k]<x)ans=k,query_pro(rs[k],x);
    else query_pro(ls[k],x);
}
void query_sub(int k,int x)
{
    if (k==0) return;
    if (num[k]>x)ans=k,query_sub(ls[k],x);
    else query_sub(rs[k],x);
}
int main()
{
    n=read();
    int opt,x;
    while (n--)
    {
        opt=read();x=read();
        switch(opt)
        {
            case 1:insert(rt,x);break;
            case 2:del(rt,x);break;
            case 3:printf("%d\n",query_rank(rt,x));break;
            case 4:printf("%d\n",query_num(rt,x));break;
            case 5:ans=0;query_pro(rt,x);printf("%d\n",num[ans]);break;
            case 6:ans=0;query_sub(rt,x);printf("%d\n",num[ans]);break;
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值