zoukankan      html  css  js  c++  java
  • 【模板】替罪羊树

    同【普通平衡树】

    • 替罪羊树单次操作的均摊复杂度为 (O(logn))
    • 由于替罪羊树的删除方式为懒惰删除,因此在查询第 K 大和查排名时必须考虑子树实际的大小。
    • 由于懒惰删除的效果,Treap 式的前驱后继查询方式对替罪羊树并不适用,需要换成查排名或求第 K 大的方式处理。
      代码如下
    /*All the functions are recursive.*/
    #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
    ",getrank(root,val));
    		else if(opt==4)printf("%d
    ",kth(root,val));
    		else if(opt==5)printf("%d
    ",kth(root,lower(root,val)));
    		else if(opt==6)printf("%d
    ",kth(root,upper(root,val)));
    	}
    	return 0;
    }
    
  • 相关阅读:
    CS027th: 6papers
    MATH026th: 《矩斋筹算丛刻》
    MATH026th: 《古今算学丛书》目录
    Compiler25th005: Excel Compiler
    AIIE25th004: 2020aiie在合肥举办
    AIIE21th003: 2021年第二届国际工业工程和人工智能大会(IEAI 2021)
    ComPiler200004:Library-Oriented Programming
    ComPiler200003:Story-Oriented Programming
    ComPiler200002:Growing a Compiler
    conda
  • 原文地址:https://www.cnblogs.com/wzj-xhjbk/p/10387748.html
Copyright © 2011-2022 走看看