[luogu3369]普通平衡树(替罪羊树模板)

解题关键:由于需要根据平衡进行重建,所以不能进行去重,否则无法保证平衡性。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<iostream>
#include<cmath>
#include<vector>
using namespace std;
typedef long long ll;

const double alpha=0.7;
const int N=1e5+500;
int n;

namespace ScapegoatTree{
    struct node{
        int l,r,v,sz,valid;
        bool del;
    }t[N<<2];
    int tot=0,rt=0;
#define ls(o) t[o].l
#define rs(o) t[o].r
#define pb push_back
    int new_node(int x){++tot;t[tot].l=t[tot].r=0;t[tot].v=x;t[tot].sz=t[tot].valid=1;t[tot].del=0;return tot;}
    bool Bad(int o){
        return (double)t[ls(o)].sz>alpha*t[o].sz||(double)t[rs(o)].sz>alpha*t[o].sz;
    }
    void Updata(int o){
        t[o].sz=t[ls(o)].sz+t[rs(o)].sz+1;
        t[o].valid=t[ls(o)].valid+t[rs(o)].valid+!t[o].del;
    }
    void Dfs(int o,std::vector<int> &v){
        if(!o) return;
        Dfs(ls(o),v);
        if(!t[o].del) v.pb(o);
        Dfs(rs(o),v);
    }
    int Build(std::vector<int> &v,int l,int r){
        if(l>r) return 0;//原因是右边界不包含
        int mid=(l+r)>>1,o=v[mid];
        ls(o)=Build(v,l,mid-1);
        rs(o)=Build(v,mid+1,r);
        Updata(o);
        return o;
    }
    void ReBuild(int &o){
        std::vector<int>v;
        Dfs(o,v);
        o=Build(v,0,(int)v.size()-1);
    }
    void Insert(int x,int &o){
        if(!o){
            o=new_node(x);
            return ;
        }
        if(x>=t[o].v) Insert(x,rs(o));
        else Insert(x,ls(o));
        Updata(o);
        if(Bad(o)) ReBuild(o);
        return;
    }
    //del with rnk
    void Delete(int o,int Rnk){
        if(!t[o].del&&Rnk==t[ls(o)].valid+1) {
            t[o].del=1;
            --t[o].valid;
            return;
        }
        if(Rnk<=t[ls(o)].valid+!t[o].del) Delete(ls(o),Rnk);
        else Delete(rs(o),Rnk-t[ls(o)].valid-!t[o].del);
        Updata(o);
    }
    int GetRank(int o,int x){
        int ans=1;
        while(o){
            if(t[o].v>=x) o=ls(o);
            else{
                ans+=t[ls(o)].valid+!t[o].del;
                o=rs(o);
            }
        }
        return ans;
    }
    int FindKth(int o,int x) {
        while(o){
            if(!t[o].del&&t[ls(o)].valid+1==x) {return t[o].v;}
            if(t[ls(o)].valid>=x) o=ls(o);
            else {
                x-=t[ls(o)].valid+!t[o].del;
                o=rs(o);
            }
        }
    }
    int GetPred(int o,int x){
        return FindKth(o,GetRank(o,x)-1);
    }
    int GetSucc(int o,int x){
        return FindKth(o,GetRank(o,x+1));
    }
}
using namespace ScapegoatTree;

int main() {
    scanf("%d",&n);
    rt=0;
    while(n--) {
        int op,x;
        scanf("%d%d",&op,&x);
        if(op==1) Insert(x,rt);
        if(op==2) Delete(rt,GetRank(rt,x));
        if(op==3) printf("%d\n",GetRank(rt,x));
        if(op==4) printf("%d\n",FindKth(rt,x));
        if(op==5) printf("%d\n",GetPred(rt,x));
        if(op==6) printf("%d\n",GetSucc(rt,x));
    }
    return 0;
}

 

posted @ 2019-02-14 16:16  Elpsywk  阅读(193)  评论(0编辑  收藏  举报