码迷,mamicode.com
首页 > 其他好文 > 详细

【模板】替罪羊树

时间:2019-02-16 15:09:17      阅读:176      评论:0      收藏:0      [点我收藏+]

标签:include   scan   ace   can   排名   rebuild   root   void   dfs   

同【普通平衡树】

  • 替罪羊树单次操作的均摊复杂度为 \(O(logn)\)
  • 由于替罪羊树的删除方式为懒惰删除,因此在查询第 K 大和查排名时必须考虑子树实际的大小。
  • 由于懒惰删除的效果,Treap 式的前驱后继查询方式对替罪羊树并不适用,需要换成查排名或求第 K 大的方式处理。
    代码如下
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const double alpha=0.7;

struct node{
    #define ls(x) t[x].lc
    #define rs(x) t[x].rc
    int lc,rc,val,size,sum,cnt;
}t[maxn];
int tot,root;
inline int newnode(int val){
    ++tot,t[tot].val=val,t[tot].cnt=t[tot].sum=t[tot].size=1;
    return tot;
}
inline bool isbad(int x){
    return (double)max(t[ls(x)].sum,t[rs(x)].sum)>t[x].sum*alpha;
}
inline void pushup(int x){
    t[x].size=t[ls(x)].size+t[rs(x)].size+t[x].cnt;
    t[x].sum=t[ls(x)].sum+t[rs(x)].sum+t[x].cnt;
}
inline void dfs(int x,vector<int> &v){
    if(ls(x))dfs(ls(x),v);
    if(t[x].cnt)v.push_back(x);
    if(rs(x))dfs(rs(x),v);
}
inline int build(int l,int r,vector<int> &v){
    if(l>r)return 0;
    int mid=l+r>>1;
    int x=v[mid];
    ls(x)=build(l,mid-1,v),rs(x)=build(mid+1,r,v);
    pushup(x);
    return x;
}
inline void rebuild(int &x){
    vector<int> v;
    dfs(x,v);
    x=build(0,v.size()-1,v);
}
void insert(int &x,int val){
    if(!x)x=newnode(val);
    else if(val==t[x].val)++t[x].cnt;
    else if(val<t[x].val)insert(ls(x),val);
    else insert(rs(x),val);
    pushup(x);
    if(isbad(x))rebuild(x);
}
void remove(int &x,int val){
    if(!x)return;
    else if(t[x].val==val)--t[x].cnt;
    else if(val<t[x].val)remove(ls(x),val);
    else remove(rs(x),val);
    pushup(x);
    if(isbad(x))rebuild(x);
}
int kth(int x,int k){//cmp with size -> we can ignore the remove tag
    if(k<=t[ls(x)].size)return kth(ls(x),k);
    else if(k>t[ls(x)].size+t[x].cnt)return kth(rs(x),k-t[ls(x)].size-t[x].cnt);
    else return t[x].val;
}
int getrank(int x,int val){//cmp with size -> we can ignore the remove tag
    if(val==t[x].val)return t[ls(x)].size+1;
    else if(val<t[x].val)return getrank(ls(x),val);
    else return getrank(rs(x),val)+t[ls(x)].size+t[x].cnt;
}
int upper(int x,int val){
    if(!x)return 1;
    else if(t[x].cnt&&val==t[x].val)return t[x].cnt+t[ls(x)].size+1;
    else if(val<t[x].val)return upper(ls(x),val);
    else return t[x].cnt+t[ls(x)].size+upper(rs(x),val);
}
int lower(int x,int val){
    if(!x)return 0;
    else if(t[x].cnt&&val==t[x].val)return t[ls(x)].size;
    else if(val<t[x].val)return lower(ls(x),val);
    else return t[x].cnt+t[ls(x)].size+lower(rs(x),val);
}

int main(){
    int n;scanf("%d",&n);
    while(n--){
        int opt,val;scanf("%d%d",&opt,&val);
        if(opt==1)insert(root,val);
        else if(opt==2)remove(root,val);
        else if(opt==3)printf("%d\n",getrank(root,val));
        else if(opt==4)printf("%d\n",kth(root,val));
        else if(opt==5)printf("%d\n",kth(root,lower(root,val)));
        else if(opt==6)printf("%d\n",kth(root,upper(root,val)));
    }
    return 0;
}

【模板】替罪羊树

标签:include   scan   ace   can   排名   rebuild   root   void   dfs   

原文地址:https://www.cnblogs.com/wzj-xhjbk/p/10387748.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!