zoukankan      html  css  js  c++  java
  • 替罪羊树

    替罪羊树

    替罪羊树是一种不用旋转的平衡树,并且速度还不错,大约在treap和splay之间吧(treap就是那么快)。

    这里用rank和xth操作实现了pre和next操作。注意rank操作找的是>=x且最小的编号,这样pre只需要查找rank(x)-1,next只需要查找rank(x+1),很优雅。

    具体证明复杂度见知乎。(我不会啊)

    #include <cstdio>
    using namespace std;
    
    const int maxn=1e5+5; const double alpha=0.7;
    struct ScpGoatTree{  //v:元素值 cnt:个数 siz:子树大小
        int root, cntn, q[maxn], cntq;
        int l[maxn], r[maxn], v[maxn], cnt[maxn], siz[maxn];
        bool bad(int x){
            int t=siz[x]*alpha+5;
            if (siz[l[x]]>t||siz[r[x]]>t) return true;
            return false;
        }
        void clear(int x){ l[x]=r[x]=siz[x]=0; }
        void up(int x){ siz[x]=siz[l[x]]+siz[r[x]]+cnt[x]; }
        void dfs(int now){
            if (!now) return;
            dfs(l[now]);
            if (cnt[now]) q[++cntq]=now;
            dfs(r[now]);
        }
        void build(int &now, int L, int R){  //now被替换成区间中点
            if (L>R) return;
            int mid=(L+R)/2; now=q[mid]; clear(now); //一定要清空节点!以免访问到原有的左右孩子
            build(l[now], L, mid-1); build(r[now], mid+1, R);
            up(now);
        }
        void rebuild(int &now){ cntq=0; dfs(now); build(now, 1, cntq); }
        void modify(int &now, int x, int c){  //注意now是父节点的孩子的引用,因此可以直接改变
            if (!now) now=++cntn, v[now]=x;  //如果没有这个节点就先新建一个(只有插入操作可能触发)
            siz[now]+=c;
            if (x==v[now]){ cnt[now]+=c; return; }
            if (x<v[now]) modify(l[now], x, c);
            if (x>v[now]) modify(r[now], x, c);
            if (bad(now)) rebuild(now);
        }
        int rank(int now, int x){  //找>=x的点的排名。
            //如果要写<=x的点的排名,那么会不优雅
            int ans=0;
            while (now){
                if (x==v[now]) return ans+siz[l[now]]+1;
                if (x<v[now]) now=l[now];
                if (x>v[now]) ans+=siz[l[now]]+cnt[now], now=r[now];
            }
            return ans+1;
        }
        int xth(int now, int x){
            int need;
            while (now){
                need=x-siz[l[now]];  //除了左子树还需要的点
                if (need>0&&need<=cnt[now]) return v[now];
                if (need<=0) now=l[now];
                else x-=siz[l[now]]+cnt[now], now=r[now];
            }
            return -1;
        }
        void printtree(){
            printf("%d
    ", v[root]);
            for (int i=1; i<=cntn; ++i)
                printf("%d %d %d
    ", v[i], v[l[i]], v[r[i]]);
            puts("");
        }
    }sgt;
    int n, op, x;
    
    int main(){
        scanf("%d", &n);
        for (int i=1; i<=n; ++i){
            scanf("%d%d", &op, &x);
            if (op==1) sgt.modify(sgt.root, x, 1);
            if (op==2) sgt.modify(sgt.root, x, -1);
            if (op==3) printf("%d
    ", sgt.rank(sgt.root, x));
            if (op==4) printf("%d
    ", sgt.xth(sgt.root, x));
            if (op==5){
                int k=sgt.rank(sgt.root, x)-1;
                printf("%d
    ", sgt.xth(sgt.root, k));
            }
            if (op==6){
                int k=sgt.rank(sgt.root, x+1);
                printf("%d
    ", sgt.xth(sgt.root, k));
            }
            //sgt.printtree();
        }
        return 0;
    }
    
  • 相关阅读:
    PAT (Advanced Level) 1114. Family Property (25)
    PAT (Advanced Level) 1113. Integer Set Partition (25)
    PAT (Advanced Level) 1112. Stucked Keyboard (20)
    PAT (Advanced Level) 1111. Online Map (30)
    PAT (Advanced Level) 1110. Complete Binary Tree (25)
    PAT (Advanced Level) 1109. Group Photo (25)
    PAT (Advanced Level) 1108. Finding Average (20)
    PAT (Advanced Level) 1107. Social Clusters (30)
    PAT (Advanced Level) 1106. Lowest Price in Supply Chain (25)
    PAT (Advanced Level) 1105. Spiral Matrix (25)
  • 原文地址:https://www.cnblogs.com/MyNameIsPc/p/9062678.html
Copyright © 2011-2022 走看看