loj10146. 「一本通 4.6 练习 3」普通平衡树(loj104. 普通平衡树 )

思路:

  十分经典的treap板子题

#include<cstdio>
#include<iostream>
#include<cstdlib>
using namespace std;
const int maxn = 100010;
inline void qread(int &x){
    x = 0;
    register int ch = getchar(), flag = 0;
    while(ch < '0' || ch > '9')        {if(ch == '-')    flag = 1;    ch = getchar();}
    while(ch >= '0' && ch <= '9')    x = 10 * x + ch - 48, ch = getchar();
    if(flag)    x = -x;
}
#define l(x) c[x][0]
#define r(x) c[x][1] 
int rt = 0, tpn, v[maxn], c[maxn][2], R[maxn], sz[maxn], vn[maxn];
inline void update(const int &x){
    sz[x] = sz[l(x)] + sz[r(x)] + vn[x];
}
inline void zap(int &x){
    int t = r(x);
    r(x) = l(t);
    l(t) = x;
    update(x);
    update(t);
    x = t;
}
inline void zip(int &x){
    int t = l(x);
    l(x) = r(t);
    r(t) = x;
    update(x);
    update(t);
    x = t;
}
void insert(int &x, int w){
    if(!x){x = ++tpn; v[x] = w;    R[x] = rand();    vn[x] = sz[x] = 1;    return ;}
    if(w != v[x])    insert(c[x][v[x] < w], w);
    else            vn[x]++;
    update(x);
    if(l(x) && R[l(x)] < R[x])    zip(x);
    if(r(x) && R[r(x)] < R[x])    zap(x);
}
void pop(int &x, int w){
    if(v[x] != w)    pop(c[x][v[x] < w], w);
    else{
        if(vn[x] > 1)    vn[x]--;
        else if(!l(x) || !r(x))    x = l(x) | r(x);
        else{
            if(R[l(x)] < R[r(x)])    zip(x), pop(x, w);
            else                    zap(x), pop(x, w);
        }
    }
    update(x);
}
int findk(int x, int k){
    if(k >= sz[l(x)] + 1 && k <= sz[l(x)] + vn[x])    return v[x];
    if(k <= sz[l(x)])                                return findk(l(x), k);
    return findk(r(x), k - sz[l(x)] - vn[x]);
}
int findr(int x, int w){
    int res = 0;
    while(x){
        if(v[x] == w)    return res + sz[l(x)] + 1;
        if(v[x] > w)    x = l(x);
        else            res += sz[l(x)] + vn[x], x = r(x);
    }
    return res;
}
int pre(int x, int w){
    int res;
    while(x){
        if(v[x] < w)    res = v[x], x = r(x);
        else            x = l(x);
    }
    return res;
}
int nxt(int x, int w){
    int res;
    while(x){
        if(v[x] <= w)    x = r(x);
        else            res = v[x], x = l(x);
    }
    return res;
}
int main(void)
{
    srand(11535);
    int n;
    qread(n);
    while(n--){
        int op, x;
        qread(op);
        qread(x);
        switch(op){
            case 1:
                insert(rt, x);
                break;
            case 2:
                pop(rt, x);
                break;
            case 3:
                printf("%d\n", findr(rt, x));
                break;
            case 4:
                printf("%d\n", findk(rt, x));
                break;
            case 5:
                printf("%d\n", pre(rt, x));
                break;
            case 6:
                printf("%d\n", nxt(rt, x));
                break;                    
        }
    }
}

 

转载于:https://www.cnblogs.com/junk-yao-blog/p/9483933.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值