难以想象..

替罪羊树只插入远远慢于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)

原文地址:https://www.cnblogs.com/tmzbot/p/5576154.html