BZOJ3224无旋treap

先diss一波洛谷P3835 这道题数据巨弱 写了一个假的可持久化treap 居然过了 导致之后真正的可持久化treap疯狂wa

最后选择放弃这道题 换了LOJ的一道模板题

普通的无旋treap还是比较简单的

BZOJ3224

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
struct node
{
    int ls,rs,value,rand,siz;
}tree[maxn];
int seed=233,root,siz;
int Rand()
{
    return seed=seed*48271%2147483647;
}
void reset(int now)
{
    tree[now].siz=tree[tree[now].ls].siz+tree[tree[now].rs].siz+1;
}
int merge(int a,int b)
{
    if(!a||!b) return a|b;
    if(tree[a].rand<tree[b].rand)
    {
        tree[a].rs=merge(tree[a].rs,b);
        reset(a);
        return a;
    }
    else
    {
        tree[b].ls=merge(a,tree[b].ls),reset(b);
        return b;
    }
}
pair<int,int> split(int now,int num)
{
    if(!now) return make_pair(0,0);
    int ls=tree[now].ls;
    int rs=tree[now].rs;
    if(num==tree[ls].siz)
    {
        tree[now].ls=0,reset(now);
        return make_pair(ls,now);
    }
    if(num==tree[ls].siz+1)
    {
        tree[now].rs=0,reset(now);
        return make_pair(now,rs);
    }
    if(num<tree[ls].siz)
    {
        pair<int,int> T=split(ls,num);
        tree[now].ls=T.second,reset(now);
        return make_pair(T.first,now);
    }
    else
    {
        pair<int,int> T=split(rs,num-tree[ls].siz-1);
        tree[now].rs=T.first,reset(now);
        return make_pair(now,T.second);
    }
}
int getrank(int now,int num)
{
    int ret=0,t=1e9;
    while(now)
    {
        if(num<=tree[now].value)
        {
            if(num==tree[now].value)
                t=min(t,ret+tree[tree[now].ls].siz+1);
            now=tree[now].ls;
        }
        else ret+=tree[tree[now].ls].siz+1,now=tree[now].rs;
    }
    return t==1e9?ret:t;
}
int getnum(int now,int num)
{
    while(1)
    {
        if(tree[tree[now].ls].siz==num-1)
            return tree[now].value;
        if(tree[tree[now].ls].siz>num-1)
            now=tree[now].ls;
        else num-=tree[tree[now].ls].siz+1,now=tree[now].rs;
    }
}
int lower(int now,int num)
{
    int ret;
    while(now)
    {
        if(tree[now].value<num)
            ret=tree[now].value,now=tree[now].rs;
        else now=tree[now].ls;
    }
    return ret;
}
int upper(int now,int num)
{
    int ret;
    while(now)
    {
        if(tree[now].value>num)
            ret=tree[now].value,now=tree[now].ls;
        else now=tree[now].rs;
    }
    return ret;
}
void insert(int num)
{
    int r=getrank(root,num);
    int now;
    pair<int,int> t=split(root,r);
    now=++siz;
    tree[now].value=num,tree[now].rand=Rand(),tree[now].siz=1;
    root=merge(t.first,siz);
    root=merge(root,t.second);
}
void del(int num)
{
    int r=getrank(root,num);
    pair<int,int> t1=split(root,r),t2=split(t1.first,r-1);
    root=merge(t2.first,t1.second);
}
int main()
{
    int n;
    scanf("%d",&n);
    while(n--)
    {
        int op,x;
        scanf("%d%d",&op,&x);
        switch(op)
        {
            case 1:insert(x);break;
            case 2:del(x);break;
            case 3:printf("%d\n",getrank(root,x));break;
            case 4:printf("%d\n",getnum(root,x));break;
            case 5:printf("%d\n",lower(root,x));break;
            case 6:printf("%d\n",upper(root,x));break;
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值