BZOJ3224: Tyvj 1728 普通平衡树(无旋Treap/替罪羊)

传送门

题意:
平衡树的一系列操作。

题解:无旋Treap/替罪羊

作为一个用Splay水过无数道题的人,第一次写无旋Treap表示很慌。。

#include<bits/stdc++.h>
using namespace std;
typedef unsigned int uint;
struct IO{
    streambuf *ib,*ob;
    inline void init(){
        ios::sync_with_stdio(false);
        cin.tie(NULL);cout.tie(NULL);
        ib=cin.rdbuf();ob=cout.rdbuf();
    }
    inline int read(){
        char ch=ib->sbumpc();int i=0,f=1;
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=ib->sbumpc();}
        while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=ib->sbumpc();}
        return i*f;
    }
    inline void W(long long x){
        static int buf[50];
        if(!x){ob->sputc('0');return;}
        if(x<0){ob->sputc('-');x=-x;}
        while(x)buf[++buf[0]]=x%10,x/=10;
        while(buf[0])ob->sputc(buf[buf[0]--]+'0');
    }
    inline uint unit(){
        static uint state0=23333;
        state0^=state0<<13;
        state0^=state0<<17;
        state0^=state0>>5;
        return state0;
    }
}io;

const int Maxn=1e5+50;
int n;
struct node{
    node *lc,*rc;
    int sze,val;
    uint pri;
    node();
    inline void upt(){
        sze=lc->sze+rc->sze+1;
    }
}Pool[Maxn],*pool=Pool,*null=Pool;
node::node():lc(null),rc(null){}
typedef pair<node*,node*> pii;
struct RecyclePool{
    node *que[Maxn];
    int tail;
    inline node* newnode(int val){
        static node* tmp;
        tmp=(tail?que[tail--]:++pool);
        tmp->lc=tmp->rc=null;
        tmp->sze=1;tmp->val=val;tmp->pri=io.unit();
        return tmp;
    }
}recyclepool;

struct Treap{
    node *rt;
    Treap():rt(null){}
    inline int getrank(int val){
        node *tmp=rt;int k=0;
        if(tmp==null)return 0;
        while(tmp!=null){
            if(tmp->val<val){k+=(tmp->lc->sze+1);tmp=tmp->rc;}
            else tmp=tmp->lc;
        }
        return k;
    }
    inline node* merge(node *x,node *y){
        if(x==null)return y;if(y==null)return x;
        if(x->pri<y->pri){
            x->rc=merge(x->rc,y);x->upt();
            return x;
        }
        else{
            y->lc=merge(x,y->lc);y->upt();
            return y;
        }
    }
    inline pii split(node *now,int k){
        if(now==null)return pii(null,null);
        if((now->lc->sze+1<=k)){
            pii tr=split(now->rc,k-now->lc->sze-1);
            now->rc=tr.first;now->upt();
            return pii(now,tr.second);
        }
        else{
            pii tr=split(now->lc,k);
            now->lc=tr.second;now->upt();
            return pii(tr.first,now);
        }
    }
    inline void insert(int val){
        int k=getrank(val);
        pii tr=split(rt,k);
        node *tmp=recyclepool.newnode(val);
        rt=merge(merge(tr.first,tmp),tr.second);
    }
    inline void remove(int val){
        int k=getrank(val);
        pii tr1=split(rt,k);
        pii tr2=split(tr1.second,1);
        rt=merge(tr1.first,tr2.second);
        recyclepool.que[++recyclepool.tail]=tr2.first;
    }
    inline int getkth(node *now,int k){
        if(now->lc->sze+1<k)return getkth(now->rc,k-now->lc->sze-1);
        else if(now->lc->sze+1==k)return now->val;
        return getkth(now->lc,k);
    }
}treap;
int main(){
    io.init();n=io.read();
    for(int i=1;i<=n;i++){
        int op=io.read();
        if(op==1){treap.insert(io.read());}
        else if(op==2){treap.remove(io.read());}
        else if(op==3){io.W(treap.getrank(io.read())+1);io.ob->sputc('\n');}
        else if(op==4){io.W(treap.getkth(treap.rt,io.read()));io.ob->sputc('\n');}
        else if(op==5){io.W(treap.getkth(treap.rt,treap.getrank(io.read())));io.ob->sputc('\n');}
        else {io.W(treap.getkth(treap.rt,treap.getrank(io.read()+1)+1));io.ob->sputc('\n');}
    }
}

写完替罪羊发现不重构可以过。。于是正解原来是二叉搜索树???

#include<bits/stdc++.h>
using namespace std;
const int alpha=75;
struct IO{
    streambuf *ib,*ob;
    inline void init(){
        ios::sync_with_stdio(false);
        cin.tie(NULL);cout.tie(NULL);
        ib=cin.rdbuf();ob=cout.rdbuf();
    }
    inline int read(){
        char ch=ib->sbumpc();int i=0,f=1;
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=ib->sbumpc();}
        while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=ib->sbumpc();}
        return i*f;
    }
    inline void W(int x){
        static int buf[50];
        if(!x){ob->sputc('0');ob->sputc('\n');return;}
        if(x<0){ob->sputc('-');x=-x;}
        while(x){buf[++buf[0]]=x%10;x/=10;}
        while(buf[0]){ob->sputc(buf[buf[0]--]+'0');}
        ob->sputc('\n');
    }
}io;

const int Maxn=1e5+50;
int n;
struct node{
    node *lc,*rc;
    node():lc(NULL),rc(NULL){}
    int sze,val,cnt;
    inline void upt(){
        sze=lc->sze+rc->sze+cnt;
    }
}Pool[Maxn],*pool=Pool,*null=Pool,*rt=null;

inline node* newnode(int val){
    ++pool;
    pool->lc=pool->rc=null;
    pool->sze=pool->cnt=1;pool->val=val;
    return pool;
}
inline void insert_val(node*& now,int val,node**&p){
    if(now==null){now=newnode(val);return;}
    if(val<now->val)insert_val(now->lc,val,p);
    else if(val>now->val)insert_val(now->rc,val,p);
    else now->cnt++;
    now->upt();
    if(100*now->lc->sze>=now->sze*alpha||100*now->rc->sze>=now->sze*alpha)p=&now;
}
inline void erase_val(node*& now,int val,node **&p){
    if(now->val==val)now->cnt--;
    else if(now->val<val)erase_val(now->rc,val,p);
    else erase_val(now->lc,val,p);
    now->upt();
    if(100*now->lc->sze>=now->sze*alpha||100*now->rc->sze>=now->sze*alpha)p=&now;
}
node* que[Maxn];int tail=0;
inline void traval(node *p){
    if(p->lc->sze)traval(p->lc);
    if(p->cnt)que[++tail]=p;
    if(p->rc->sze)traval(p->rc);
}
inline node* build(int l,int r){
    static int cnt;
    if(r<l)return null;
    if(l==r){
        que[l]->lc=que[l]->rc=null;
        que[l]->sze=que[l]->cnt;
        return que[l];
    }
    int mid=(l+r)>>1;
    node* tmp=que[mid];
    tmp->lc=build(l,mid-1);
    tmp->rc=build(mid+1,r);
    tmp->upt();
    return tmp;
}
inline void rebuild(node *&p){
    tail=0;traval(p);
    int l=1,r=tail;
    p=build(l,r);
}
inline void insert(node*& now,int val){
    node **p=&null;
    insert_val(now,val,p);
    if(*p!=null)rebuild(*p);
}
inline void del(node*& now,int val){
    node **p=&null;
    erase_val(now,val,p);
    if(*p!=null)rebuild(*p);
}
inline int getrank(int val){
    int k=0;node *tmp=rt;
    while(tmp!=null){
        if(tmp->val<val)k+=tmp->lc->sze+tmp->cnt,tmp=tmp->rc;
        else tmp=tmp->lc;
    }
    return k+1;
}
inline int getkth(node *now,int kth){
    if(now->lc->sze>=kth)return getkth(now->lc,kth);
    else if(now->lc->sze+now->cnt>=kth)return now->val;
    else return getkth(now->rc,kth-now->lc->sze-now->cnt);
}
inline int getpre(int val){
    node *tmp=rt;int last;
    while(tmp!=null){
        if(tmp->val>=val)tmp=tmp->lc;
        else last=tmp->val,tmp=tmp->rc;
    }
    return last;
}
inline int getsuf(int val){
    node *tmp=rt;int last;
    while(tmp!=null){
        if(tmp->val<=val)tmp=tmp->rc;
        else last=tmp->val,tmp=tmp->lc;
    }
    return last;
}
int main(){
    io.init();n=io.read();
    for(int i=1;i<=n;i++){
        int op=io.read();
        if(op==1){
            insert(rt,io.read());
        }
        else if(op==2){
            del(rt,io.read());
        }
        else if(op==3){
            io.W(getrank(io.read()));
        }
        else if(op==4){
            io.W(getkth(rt,io.read()));
        }
        else if(op==5){
            io.W(getkth(rt,getrank(io.read())-1));
        }           
        else io.W(getkth(rt,getrank(io.read()+1)));
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值