• 难以想象..


    替罪羊树只插入远远慢于std::set...

    我比较了sgt的4种实现..

    Set.zball

    /// public domain
    #include <set>
    using namespace std;
    set<int> p;
    int main(){
    	for(int i=1;i<=1000000;++i) p.insert(i);
    	return 0;
    }
    
    • no opt: 0.64s
    • -O2: 0.24s

    ScapegoatTree.zball

    /// 这份代码妥妥的public domain.
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    typedef double fl;
    typedef unsigned long long ull;
    
    const fl  alpha  = 0.75;
    const fl  ialpha = 1./alpha;
    const int maxn   = 1001000;
    const ull ullMax = 9223372036854775807;
    
    namespace AlphaProcessor{
    	/// Process alpha usable routines
    	int HeightMin[200];
    	inline void InitMins(double p=0.){
    		for(int i=1;(p=pow(ialpha,i))<=maxn*ialpha*ialpha*ialpha;++i) HeightMin[i]=int(p);
    	}
    } using namespace AlphaProcessor;
    
    namespace ScapegoatTree{
    	#define fsiz(x) (x?x->siz:0)
    	struct sgtNode{
    		int val,siz;
    //		ull id,idl,idr;
    		sgtNode*l,*r,*f;
    		inline sgtNode*pu(){
    			siz=fsiz(l)+fsiz(r)+1;
    			return this;
    		}
    	};
    	struct sgt{
    		sgtNode tr[maxn],*trp,*root,*trr[maxn];
    		sgt():trp(tr){}
    		sgtNode* get(int val/*,ull idl,ull idr*/,sgtNode*fa){
    			sgtNode*ret=trp++;
    //			ull iid=(idl+idr)>>1;
    			*ret=(sgtNode){
    				val,  1,
    //				iid , idl , idr,
    				NULL, NULL, fa
    			};
    			return ret;
    		}
    		sgtNode*build(sgtNode*fa,int l,int r/*,ull idl,ull idr*/){
    			if(l>r) return NULL;
    			int mid=(l+r)>>1,pval=trr[mid]->val;
    //			ull iid=(idl+idr)>>1;
    			if(l==r){
    				*trr[mid]=(sgtNode){
    					pval, 1,
    //					iid , idl , idr,
    					NULL, NULL, fa
    				}; return trr[mid];
    			}else{
    				*trr[mid]=(sgtNode){
    					pval, 0,
    //					iid , idl , idr,
    					build(trr[mid],l,mid-1/*,idl,iid-1*/),
    					build(trr[mid],mid+1,r/*,iid+1,idr*/),
    					fa
    				}; return trr[mid]->pu();
    			}
    		}
    		int flatten(sgtNode*flattenNode,int trrIndex=1){
    			if(!flattenNode) return trrIndex;
    			trrIndex=flatten(flattenNode->l,trrIndex);
    			trr[trrIndex++]=flattenNode;
    			trrIndex=flatten(flattenNode->r,trrIndex);
    			return trrIndex;
    		}
    		sgtNode*rebuild(sgtNode*rootRebuild){
    //			ull idl=rootRebuild->idl, idr=rootRebuild->idr;
    			int flattenLen=flatten(rootRebuild)-1;
    			return build(NULL,1,flattenLen/*,idl,idr*/);
    		}
    		sgtNode*insert(int val,int dep=1){
    			sgtNode*proot=root, *pfat=NULL;
    			while(proot){ ++proot->siz, ++dep;
    				pfat=proot;
    				if(val<=proot->val) proot=proot->l;
    				else proot=proot->r;
    			} sgtNode*ret=NULL;
    			if(pfat){
    				if(val<=pfat->val) ret=(pfat->l=get(val/*,pfat->idl,pfat->id-1*/,pfat));
    				else ret=(pfat->r=get(val/*,pfat->id+1,pfat->idr*/,pfat));
    			}else root=ret=get(val/*,0,ullMax*/,NULL);
    			if(HeightMin[dep]>root->siz){
    				sgtNode*rr=ret->f;
    				while(rr){
    					int p=int(((rr->siz)*alpha));
    					if((fsiz(rr->l)>p)||(fsiz(rr->r)>p)){
    						sgtNode*p=rr->f;
    						sgtNode*res=rebuild(rr);
    						if(p){
    							res->f=p;
    							if(p->l==rr) p->l=res;
    							else p->r=res;
    						}else root=res;
    						break;
    					}
    					rr=rr->f;
    				}
    			} return ret;
    		}
    	} vsgt;
    } using namespace ScapegoatTree;
    
    sgtNode* vk[maxn];
    
    int main(){
    	AlphaProcessor::InitMins();
    	for(int i=1;i<=1000000;++i){
    		vk[i]=vsgt.insert(i);
    	}
    	return 0;
    }
    
    • no opt: 0.75s
    • -O2: 0.4s
    • alpha=0.805: 0.643s
    • alpha=0.805 -O2: 0.321s

    ScapegoatTree.OIRed2015

    /// py交易来的代码..
    /// 版权归OIRed2015所有, 转载请询问其本人. QQ: 305626341
    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<bitset>
    #include<set>
    #include<map>
    #include<cmath>
    #include<vector>
    #include<queue>
    #include<ctime>
    #include<cassert> 
    using namespace std;
    typedef double db;
    typedef long double ld; 
    typedef unsigned long long ull; 
    typedef long long ll;
    typedef unsigned int uint; 
    #define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
    #define rep2(i,a,b) for(int (i)=(a);(i)<(b);(i)++)
    #define per(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)
    #define Rep(p,x) for(int (p)=head[(x)];(p);(p)=nxt[(p)])
    #define Rep2(p,x) for(int (p)=cur[(x)];(p);(p)=nxt[(p)])
    #define ms(x,y) memset(x,y,sizeof x)
    #define w1 first
    #define w2 second
    #define mp make_pair
    #define pa pair<int,int>
    #define pb push_back
    #define ins insert
    #define lowbit(x) ((x)&(-x))
    #define sqr(x) ((x)*(x))
    #define SZ(x) (int((x).size()))
    #define cle(x) ((x).clear())
    template<class T>inline void rread(T&num){
        num=0;T f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')num=num*10+ch-'0',ch=getchar();
        num*=f;
    }
    inline int getgcd(int x,int y){if(!x)return y;return getgcd(y%x,x);}
    inline ll getlcm(int x,int y){return (ll)x/getgcd(x,y)*y;}
    inline ll getgcd(ll x,ll y){if(!x)return y;return getgcd(y%x,x);}
    inline ll getlcm(ll x,ll y){return x/getgcd(x,y)*y;}
    inline int power(int x,int k,int p){int res=1;for(;k;k>>=1,x=(ll)x*x%p)if(k&1)res=(ll)res*x%p;return res;}
    inline ll power(ll x,ll k,ll p){ll res=1;for(;k;k>>=1,x=x*x%p)if(k&1)res=res*x%p;return res;}
    const double pi=acos(-1);
    inline void judge(){
        freopen("input.txt","r",stdin);
    } 
    //********************************head*************************************
    const int maxn=1000005;
    int arc[maxn];
    typedef int node;
    namespace Sgt{
        const db alpha=0.75;
        int nowx,root,ndtot,top;
        int sz[maxn],ls[maxn],rs[maxn];
        int st[maxn];
        int key[maxn];
        inline void dfs(int x){
            if(!x)return;
            dfs(ls[x]);
            st[++top]=x;
            dfs(rs[x]);
        }
        inline int build(int L,int R){
            if(L>R)return 0;
            int Mid=(L+R)>>1,now=st[Mid];
            sz[now]=R-L+1;
            ls[now]=build(L,Mid-1);
            rs[now]=build(Mid+1,R);
            return now;
        }
        inline void rebuild(int &x){
            top=0;dfs(x);
            x=build(1,top);
            nowx=0;
        }
        inline void update(int x){
            sz[x]=sz[ls[x]]+sz[rs[x]]+1;
        }
        inline int insert(int &x,node num){
            if(!x){
                x=++ndtot;
                key[x]=num;
                sz[x]=1;
                return x;
            }
            if(num==key[x])return x;
            int res;
            if(num<key[x]){
                res=insert(ls[x],num);
                if(sz[ls[x]]<sz[x]*alpha){
                    if(nowx)rebuild(ls[x]);
                }else nowx=x;
            }else{
                res=insert(rs[x],num);
                if(sz[rs[x]]<sz[x]*alpha){
                    if(nowx)rebuild(rs[x]);
                }else nowx=x;
            }
            update(x);
            return res;
        }
        #undef mid
    }using namespace Sgt;
    int n,m;
    int main(){
        for(int i=1;i<=1000000;++i){
            insert(root,i);
            if(nowx) rebuild(root);
        }
        return 0;
    }
    
    • no opt: 0.933s
    • -O2: 0.466s

    ScapegoatTree.Kuangbin

    /// 听说是Kuangbin的模板. 修改自http://blog.csdn.net/u010660276/article/details/44162183 ,如果博主认为造成了不好的影响请联系我.
    #include<iostream>
    #include<cstdio>
    #include<string>
    #include<cstring>
    #include<vector>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<map>
    #include<set>
    #include<algorithm>
    using namespace std;
    const int maxn=1000010;
    const double alpha=0.75;
    int N;
    struct Node
    {
        Node *ch[2];
        int size,key,nodeCount;
        bool exist;
        bool isBad()
        {
            return ch[0]->nodeCount>alpha*nodeCount+5||ch[1]->nodeCount>alpha*nodeCount+5;
        }
        void pushup()
        {
            size=exist+ch[0]->size+ch[1]->size;
            nodeCount=1+ch[0]->nodeCount+ch[1]->nodeCount;
        }
    };
    struct ScapeGoatTree
    {
        Node pool[maxn];
        Node *tail,*root,*null;
        Node *bc[maxn];
        int bc_top;
        void init()
        {
            tail=pool;
            null=tail++;
            null->ch[0]=null->ch[1]=null;
            null->size=null->key=null->nodeCount=0;
            root=null;
            bc_top=0;
        }
        Node *newNode(int key)
        {
            Node *p;
            if(bc_top)p=bc[--bc_top];
            else p=tail++;
            p->ch[0]=p->ch[1]=null;
            p->size=1;
            p->key=key;
            p->nodeCount=1;
            p->exist=true;
            return p;
        }
        void Travel(Node *p,vector<Node *>&v)
        {
            if(p==null)return;
            Travel(p->ch[0],v);
            if(p->exist)v.push_back(p);
            else bc[bc_top++]=p;
            Travel(p->ch[1],v);
        }
        Node *divide(vector<Node *>&v,int l,int r)
        {
            if(l>=r)return null;
            int mid=(l+r)>>1;
            Node *p=v[mid];
            p->ch[0]=divide(v,l,mid);
            p->ch[1]=divide(v,mid+1,r);
            p->pushup();
            return p;
        }
        void rebuild(Node *&p)
        {
            vector<Node *>v;
            Travel(p,v);
            p=divide(v,0,v.size());
        }
        Node **insert(Node *&p,int val)
        {
            if(p==null)
            {
                p=newNode(val);
                return &null;
            }
            else
            {
                p->size++;
                p->nodeCount++;
                int d=(val>=p->key);
                Node **res=insert(p->ch[d],val);
                if(p->isBad())res=&p;
                return res;
            }
        }
        void insert(int val)
        {
            Node **p=insert(root,val);
            if(*p!=null)rebuild(*p);
        }
        void erase(Node *p,int id)
        {
            if(p->exist&&id==p->ch[0]->size+1)
            {
                p->exist=0;
                p->size--;
                return;
            }
            p->size--;
            if(id<=p->ch[0]->size+p->exist)
                erase(p->ch[0],id);
            else erase(p->ch[1],id-p->ch[0]->size-p->exist);
        }
        int rank(int val)
        {
            Node *now=root;
            int ans=1;
            while(now!=null)
            {
                if(now->key>=val)now=now->ch[0];
                else
                {
                    ans+=now->ch[0]->size+now->exist;
                    now=now->ch[1];
                }
            }
            return ans;
        }
        int get_kth(int k)
        {
            Node *now=root;
            while(now!=null)
            {
                if(now->exist&&k==now->ch[0]->size+1)
                    return now->key;
                else if(now->ch[0]->size>=k)now=now->ch[0];
                else
                {
                    k-=now->ch[0]->size+now->exist;
                    now=now->ch[1];
                }
            }
        }
        void erase(int val)
        {
            erase(root,rank(val));
            if(root->size<alpha*root->nodeCount)
                rebuild(root);
        }
    }tree;
    int main()
    {
        int op,x;
        tree.init();
        for(int i=1;i<=1000000;++i) tree.insert(i);
        return 0;
    }
    

    (much slower)

    ScapegoatTree.Li Zhuohan(不知道谁,博主如果认为侵犯了您的权益请留言,我会删除代码)

    from: http://www.cnblogs.com/zhuohan123/p/3562539.html

    (略有修改)

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const double a=0.75;
    inline int getnum()
    {
        int ans=0,fh=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')fh*=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')ans=ans*10+ch-'0',ch=getchar();
        return fh*ans;
    }
    struct node{int s[2],f,size,num;}t[2100000];int tnum,root;
    inline void init()
    {
        tnum=2;root=1;
        t[1].num=-2147483647;t[1].size=2;t[1].s[1]=2;
        t[2].num=2147483647;t[2].size=1;t[2].f=1;
    }
    inline bool balance(int po)
    {
        return (double)t[po].size*a>=(double)t[t[po].s[0]].size
             &&(double)t[po].size*a>=(double)t[t[po].s[1]].size;
    }
    int E[1100000],esize;
    void travel(int po)
    {
        if(t[po].s[0])travel(t[po].s[0]);
        E[++esize]=po;
        if(t[po].s[1])travel(t[po].s[1]);
    }
    int build(int l,int r)
    {
        if(l>r)return 0;
        int mid=(l+r)/2,po=E[mid];
        t[t[po].s[0]=build(l,mid-1)].f=po;
        t[t[po].s[1]=build(mid+1,r)].f=po;
        t[po].size=t[t[po].s[0]].size+t[t[po].s[1]].size+1;
        return po;
    }
    inline void rebuild(int po)
    {
        esize=0;travel(po);
        int fa=t[po].f,ws=(t[t[po].f].s[1]==po);
        int npo=build(1,esize);
        t[t[fa].s[ws]=npo].f=fa;
        if(po==root)root=npo;
    }
    inline void insert(int num)
    {
        int now=root,npo=++tnum;
        t[npo].size=1;t[npo].num=num;
        while(true)
        {
            t[now].size++;
            bool ws=(num>=t[now].num);
            if(t[now].s[ws])now=t[now].s[ws];
            else {t[t[now].s[ws]=npo].f=now;break ;}
        }
        int inv=0;
        for(int i=npo;i;i=t[i].f)if(!balance(i))inv=i;
        if(inv)rebuild(inv);
    }
    inline int rank(int num)
    {
        int now=root,ans=0;
        while(now)
        {
            if(t[now].num<num)ans+=t[t[now].s[0]].size+1,now=t[now].s[1];
            else now=t[now].s[0];
        }
        return ans;
    }
    inline int getkth(int kth)
    {
        int now=root;
        while(true)
        {
            if(t[t[now].s[0]].size==kth-1)return now;
            else if(t[t[now].s[0]].size>=kth)now=t[now].s[0];
            else kth-=t[t[now].s[0]].size+1,now=t[now].s[1];
        }
        return now;
    }
    inline int getn(int num)
    {
        int now=root;
        while(true)
        {
            if(t[now].num==num)return now;
            else now=t[now].s[t[now].num<num];
        }
    }
    inline void erase(int po)
    {
        if(t[po].s[0]&&t[po].s[1])
        {
            int tpo=t[po].s[0];
            while(t[tpo].s[1])tpo=t[tpo].s[1];
            t[po].num=t[tpo].num;
            po=tpo;
        }
        int son=(t[po].s[0])?t[po].s[0]:t[po].s[1],ws=(t[t[po].f].s[1]==po);
        t[t[t[po].f].s[ws]=son].f=t[po].f;
        for(int i=t[po].f;i;i=t[i].f)t[i].size--;
        if(po==root)root=son;
    }
    inline int succ(int num)
    {
        int now=root,ans=2147483647;
        while(now)
        {
            if(t[now].num>num)ans=min(ans,t[now].num),now=t[now].s[0];
            else now=t[now].s[1];
        }
        return ans;
    }
    inline int pred(int num)
    {
        int now=root,ans=-2147483647;
        while(now)
        {
            if(t[now].num<num)ans=max(ans,t[now].num),now=t[now].s[1];
            else now=t[now].s[0];
        }
        return ans;    
    }
    int main(int argc, char *argv[])
    {
        init();
        for(int i=1;i<=1000000;++i) insert(i);
        return 0;
    }
    

    (much slower)

  • 相关阅读:
    2020年4月4日训练
    HZNU Training 17 for Zhejiang Provincial Competition 2020
    [kuangbin带你飞]专题四 最短路练习
    三分法
    洛谷多校第一周续
    洛谷春季 ACM 多校训练第五周
    简单数学三月小结
    线段树&树状数组
    图论三月小结
    Java中Double保留后小数位的几种方法
  • 原文地址:https://www.cnblogs.com/tmzbot/p/5576154.html
Copyright © 2020-2023  润新知