变量/函数の定义
变量/函数名 | 定义/作用 |
---|---|
tax[] |
将树拍扁时用的临时数组 |
tail |
与 tax[] 配套使用,类似于栈顶指针 |
son[x][] |
点 \(x\) 在树上的左/右儿子 |
exist[x] |
点 \(x\) 存在与否,\(1\) 为存在 |
val[x] |
点 \(x\) 的值 |
siz[x] |
点 \(x\) 的子树一共有多少节点 |
fact[x] |
点 \(x\) 的子树实际还存在多少节点 |
rt |
树根 |
memory_pool[] |
内存池 |
origami |
记录内存池的元素个数,也用作栈顶指针 |
void buildPool() |
建立内存池 |
int Newnode() |
获取一个新节点编号 |
void Release(x) |
释放节点 \(x\),即重新放回内存池 |
void Clear(x) |
将点 \(x\) 清空 |
void Leaf(x) |
建立点 \(x\) 为叶子的信息,双儿子为 \(0\) 且子树大小为 \(1\) |
void Pushup(x) |
顾名思义,上传操作 |
bool Balance(x) |
返回树 \(x\) 平衡与否,\(1\) 为平衡 |
void Insert(x,v) |
在点 \(x\) 的子树里面插入值 \(v\) |
void Delete(x,rnk) |
在点 \(x\) 的子树里面删除排名为 \(rnk\) 的值 |
int Getrnk(v) |
获得值 \(v\) 在整棵树里的排名 |
int Getval(rnk) |
获得树里排名为 \(rnk\) 的值 |
void Recycle(x) |
回收/拍扁以 \(x\) 为根的树 |
void Setup(x,l,r) |
以 \(x\) 为树根,在 tax[] 的 \(l\) 到 \(r\) 区间中重新建树 |
void Rebuild(x) |
重建子树 \(x\) |
void Check(v) |
在树插入/删除 \(v\) 之后检查树的平衡性 |
代码
/* * @Author: Arextre * @Date: 2020-03-13 10:42:22 * @Last Modified by: Arextre * @Last Modified time: 2020-03-14 10:35:15 */ #include<cstdio> #include<vector> using namespace std; #define rep(i,__l,__r) for(signed i=(__l),i##_end_=(__r);i<=i##_end_;++i) #define fep(i,__l,__r) for(signed i=(__l),i##_end_=(__r);i>=i##_end_;--i) #define writc(a,b) fwrit(a),putchar(b) #define mp(a,b) make_pair(a,b) #define ft first #define sd second #define LL long long #define ull unsigned long long #define uint unsigned int #define pii pair< int,int > #define Endl putchar('\n') // #define FILEOI // #define int long long // #define int unsigned // #define int unsigned long long #ifdef FILEOI # define MAXBUFFERSIZE 500000 inline char fgetc(){ static char buf[MAXBUFFERSIZE+5],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,MAXBUFFERSIZE,stdin),p1==p2)?EOF:*p1++; } # undef MAXBUFFERSIZE # define cg (c=fgetc()) #else # define cg (c=getchar()) #endif template<class T>inline void qread(T& x){ char c;bool f=0; while(cg<'0'||'9'<c)f|=(c=='-'); for(x=(c^48);'0'<=cg&&c<='9';x=(x<<1)+(x<<3)+(c^48)); if(f)x=-x; } inline int qread(){ int x=0;char c;bool f=0; while(cg<'0'||'9'<c)f|=(c=='-'); for(x=(c^48);'0'<=cg&&c<='9';x=(x<<1)+(x<<3)+(c^48)); return f?-x:x; } // template<class T,class... Args>inline void qread(T& x,Args&... args){qread(x),qread(args...);} template<class T>inline T Max(const T x,const T y){return x>y?x:y;} template<class T>inline T Min(const T x,const T y){return x<y?x:y;} template<class T>inline T fab(const T x){return x>0?x:-x;} inline int gcd(const int a,const int b){return b?gcd(b,a%b):a;} inline void getInv(int inv[],const int lim,const int MOD){ inv[0]=inv[1]=1;for(int i=2;i<=lim;++i)inv[i]=1ll*inv[MOD%i]*(MOD-MOD/i)%MOD; } template<class T>void fwrit(const T x){ if(x<0)return (void)(putchar('-'),fwrit(-x)); if(x>9)fwrit(x/10); putchar(x%10^48); } inline LL mulMod(const LL a,const LL b,const LL mod){//long long multiplie_mod return ((a*b-(LL)((long double)a/mod*b+1e-8)*mod)%mod+mod)%mod; } const double ALPHA=0.7; const int INF=0x3f3f3f3f; const int MAXN=100000; int tax[MAXN+5],tail; int son[MAXN+5][2],exist[MAXN+5],val[MAXN+5],siz[MAXN+5],fact[MAXN+5],rt; int memory_pool[MAXN+5],origami;//内存池 inline void buildPool(){ origami=0; fep(i,MAXN,1)memory_pool[++origami]=i; } inline int Newnode(){ return memory_pool[origami--]; } inline void Release(const int x){memory_pool[++origami]=x;} inline void Clear(const int x){ son[x][0]=son[x][1]=exist[x]=val[x]=siz[x]=fact[x]=0; } inline void Leaf(const int x){ son[x][0]=son[x][1]=0,siz[x]=fact[x]=1; } inline void Pushup(const int x){ siz[x]=siz[son[x][0]]+siz[son[x][1]]+1; fact[x]=fact[son[x][0]]+fact[son[x][1]]+1; } inline bool Balance(const int x){ return (double)fact[x]*ALPHA>(double)Max(fact[son[x][0]],fact[son[x][1]]); } void Insert(int& x,const int v){ if(!x){ Clear(x=Newnode()); val[x]=v,exist[x]=1; Leaf(x); return; } ++siz[x],++fact[x]; if(v<=val[x])Insert(son[x][0],v); else Insert(son[x][1],v); } void Delete(const int x,const int rnk){ --fact[x]; if(exist[x] && fact[son[x][0]]+1==rnk){ exist[x]=0; return; } if(rnk<=fact[son[x][0]]+exist[x])Delete(son[x][0],rnk); else Delete(son[x][1],rnk-fact[son[x][0]]-exist[x]); } inline int Getrnk(const int v){ int x=rt,rnk=1; while(x){ if(v<=val[x])x=son[x][0]; else rnk+=fact[son[x][0]]+exist[x],x=son[x][1]; } return rnk; } inline int Getval(int rnk){ if(rnk<1 || fact[rt]<rnk)return -INF; int x=rt; while(x){ if(exist[x] && fact[son[x][0]]+1==rnk)return val[x]; else if(rnk<=fact[son[x][0]]+exist[x])x=son[x][0]; else rnk-=(fact[son[x][0]]+exist[x]),x=son[x][1]; } } void Recycle(const int x){ if(!x)return; Recycle(son[x][0]); if(exist[x])tax[++tail]=x; else Release(x); Recycle(son[x][1]); } void Setup(int& x,const int l,const int r){ int mid=(l+r)>>1;x=tax[mid]; if(l==r)return Leaf(x); if(l<mid)Setup(son[x][0],l,mid-1); else son[x][0]=0;//此句十分关键 Setup(son[x][1],mid+1,r); Pushup(x); } inline void Rebuild(int& x){ tail=0;Recycle(x); if(tail>0)Setup(x,1,tail); else x=0; } inline void Check(const int v){ if(!Balance(rt))return Rebuild(rt); int x=rt,d=(v>val[rt]); while(son[x][d]){ if(!Balance(son[x][d]))return Rebuild(son[x][d]); x=son[x][d]; d=(v>val[x]); } } int n,opt,x; signed main(){ #ifdef FILEOI freopen("file.in","r",stdin); freopen("file.out","w",stdout); #endif scanf("%d",&n); buildPool(); while(n--){ scanf("%d %d",&opt,&x); if(opt==1)Insert(rt,x),Check(x); else if(opt==2)Delete(rt,Getrnk(x)),Check(x); else if(opt==3)printf("%d\n",Getrnk(x)); else if(opt==4)printf("%d\n",Getval(x)); else if(opt==5)printf("%d\n",Getval(Getrnk(x)-1)); else if(opt==6)printf("%d\n",Getval(Getrnk(x+1)));//注意+1细节 } return 0; }
来源:https://www.cnblogs.com/Arextre/p/12490984.html