替罪羊树只插入远远慢于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.4salpha=0.805
: 0.643salpha=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)