• P3369 【模板】普通平衡树


    您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:

    1. 插入 xx 数
    2. 删除 xx 数(若有多个相同的数,因只删除一个)
    3. 查询 xx 数的排名(排名定义为比当前数小的数的个数 +1+1 )
    4. 查询排名为 xx 的数
    5. 求 xx 的前驱(前驱定义为小于 xx,且最大的数)
    6. 求 xx 的后继(后继定义为大于 xx,且最小的数)

     

    很好的模板题

    借鉴了一位在役国集选手

    #include<bits/stdc++.h>
    #define MAXN 300005
    using namespace std;
    
    struct Splay{
        int num[MAXN],ch[MAXN][2],sz[MAXN],f[MAXN],cnt[MAXN],rt,tot;
        int get(int x){
            return (x==ch[f[x]][1]);
        }
        int up(int x){
            sz[x] = cnt[x];
            if(ch[x][0])sz[x] = sz[x]+sz[ch[x][0]];
            if(ch[x][1])sz[x] = sz[x]+sz[ch[x][1]];
            return 0;
        }
        int rote(int x){
            int y = f[x],z = f[y],k = get(x),p = get(y);
            if(y==0)return 0;
            if(z)ch[z][p] = x;
            if(ch[x][k^1])f[ch[x][k^1]] = y;
            ch[y][k] = ch[x][k^1];
            ch[x][k^1] = y;
            f[x] = z;
            f[y] = x;
            up(y);up(x);
            return 0;
        }
        int splay(int x){
            for(int y = f[x];(y = f[x]);rote(x)){
                rote((get(x)==get(y))?y:x);
            }
            rt = x;
            return 0;
        }
        int rank(int x){
            int now=rt,ans=1;
            while(1){
                if(num[now]<=x){
                    ans =     ans+sz[ch[now][0]];
                    if(num[now]==x){
                    splay(now);
                    return ans;
                    }
                    ans = ans+cnt[now];
                    now = ch[now][1];
                }
                else{
                    now = ch[now][0];
                }
            }
        }
        int pre(){//前继 比她小的最大 
            int now = ch[rt][0];
            while(ch[now][1])now = ch[now][1];
            return now;
        }
        int suc(){
            int now = ch[rt][1];
            while(ch[now][0])now = ch[now][0];
            return now;
        }
        int add(int x){
            int now = rt;
            while(1){
                if(num[now]==x){
                    cnt[now]++;
                    splay(now);
                    return 0;
                }
                int to = (num[now]<x);
                if(!ch[now][to]){
                    tot++;
                    ch[now][to] = tot;
                    num[tot] = x;
                    f[tot] = now;
                    cnt[tot] = 1;
                    sz[tot] = 1;
                    splay(tot);
                    return 0;
                }
                else now = ch[now][to];
            }
        }
        int kth(int x){
            int now =rt;
            while(1){
                if(sz[ch[now][0]]<x){
                    x = x-sz[ch[now][0]];
                    if(x<=cnt[now])return num[now];
                    x = x-cnt[now];
                    now = ch[now][1];
                }
                else{
                    now = ch[now][0];
                }
            }
        }
        int del(int x){
            rank(x);
            if(cnt[rt]>=2){
                cnt[rt]--;
                sz[rt]--;
                return 0;
            }
            else{
                if((!ch[rt][0])&&(!ch[rt][1])){
                    rt = 0;
                    return 0;
                }
                if(ch[rt][0]&&(!ch[rt][1])){
                    f[ch[rt][0]] = 0;
                    rt =ch[rt][0];
                    return 0;
                }
                if((!ch[rt][0])&&ch[rt][1]){
                    f[ch[rt][1]] = 0;
                    rt =ch[rt][1];
                    return 0;
                }
                else{
                    splay(pre());
                    ch[rt][1] = ch[ch[rt][1]][1];
                    f[ch[rt][1]] = rt;
                    up(rt);
                    return 0;
                }
            }
        }
    }T;
    
    int main(){
        int n,a,b;
        cin>>n;
        for(int i=1;i<=n;i++){
            cin>>a;
            if(a==1){
                cin>>b;
                T.add(b);
            }
            else if(a==2){
                cin>>b;
                T.del(b);
            }
            else if(a==3){
                cin>>b;
                cout<<T.rank(b)<<endl;
            }
            else if(a==4){
                cin>>b;
                cout<<T.kth(b)<<endl;
            }
            else if(a==5){
                cin>>b;
                T.add(b);
                cout<<T.num[T.pre()]<<endl;
                T.del(b);
            }
            else if(a==6){
                cin>>b;
                T.add(b);
                cout<<T.num[T.suc()]<<endl;
                T.del(b);
            }
        }
    }
    View Code
  • 相关阅读:
    2021NUAA暑假集训 Day3 题解
    2021NUAA暑假集训 Day2 题解
    2021NUAA暑期模拟赛部分题解
    CodeForces 1038D Slime
    UVA 11149 Power of Matrix
    UVA 10655 Contemplation! Algebra
    UVA 10689 Yet another Number Sequence
    HDU 4549 M斐波那契数列
    HDU 4990 Reading comprehension
    CodeForces 450B Jzzhu and Sequences
  • 原文地址:https://www.cnblogs.com/shatianming/p/12234462.html
Copyright © 2020-2023  润新知