1. 程式人生 > >P3369-[模板]普通平衡樹【替罪羊樹】

P3369-[模板]普通平衡樹【替罪羊樹】

正題

評測記錄:https://www.luogu.org/recordnew/lists?uid=SSL_WYC_zombieeeeee&pid=P3369&status=&sort=0


題目大意

要求支援查詢一個數字的排名,查詢該排名的數字,插入數字,刪除數字,求前驅後繼。


解題思路

替罪羊樹


c o d e
code

#include<cstdio>
#include<algorithm>
#include<cctype>
#define alpha 0.8
#define N 100010
using namespace std;
inline int read(){
    int x(0),sign(0);
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-') sign=1;
        ch=
getchar(); } while(isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=getchar(); return sign?-x:x; } struct goat_Tree{ int l[N],r[N],size[N],val[N],valid[N],total[N]; int cur[N],memory[N]; bool exist[N]; int root,poi,pool,cnt; void ReMemory(){ for(int i=N-10;i>=1;i--) memory[
++pool]=i; } bool Isbad(int now){ if((double)valid[now]*alpha<=(double)max(valid[l[now]],valid[r[now]])) return true; else return false; } void Beat(int now){ if(!now) return; Beat(l[now]); if(exist[now]) cur[++poi]=now; else memory[++pool]=now; Beat(r[now]); } void New(int x){ l[x]=r[x]=0; total[x]=valid[x]=1; } void Build(int ls,int rs,int &now){ int mid=(ls+rs)>>1; now=cur[mid]; if(ls==rs){ New(now); return; } if(ls<mid) Build(ls,mid-1,l[now]); else l[now]=0; Build(mid+1,rs,r[now]); total[now]=total[l[now]]+total[r[now]]+1; valid[now]=valid[l[now]]+valid[r[now]]+1; } void ReBuild(int &now){ poi=0;Beat(now); if(poi) Build(1,poi,now); else now=0; } int GetRankByVal(int k){ int now=root; int ans=1; while(now){ if(val[now]>=k) now=l[now]; else{ ans+=valid[l[now]]+exist[now]; now=r[now]; } } return ans; } int GetValByRank(int k){ int now=root; while(now){ if(exist[now]&&valid[l[now]]+1==k) return val[now]; if(valid[l[now]]>=k) now=l[now]; else{ k-=valid[l[now]]+exist[now]; now=r[now]; } } } void Insert(int &now,int num){ if(!now){ now=memory[pool--];val[now]=num; New(now);exist[now]=1; return; } total[now]++;valid[now]++; if(val[now]>=num) Insert(l[now],num); else Insert(r[now],num); if(Isbad(now)) ReBuild(now); } void Remove_z(int &now,int tar){ if(exist[now]&&valid[l[now]]+1==tar){ exist[now]=0;valid[now]--; return; } valid[now]--; if(valid[l[now]]+exist[now]>=tar) Remove_z(l[now],tar); else Remove_z(r[now],tar-valid[l[now]]-exist[now]); } void Remove(int tar){ Remove_z(root,GetRankByVal(tar)); if((double)total[root]*alpha>valid[root]) ReBuild(root); } }a; int main() { int opt,x,m; a.ReMemory(); scanf("%d",&m); while(m--) { opt=read();x=read(); if(opt==1) a.Insert(a.root,x); if(opt==2) a.Remove(x); if(opt==3) printf("%d\n",a.GetRankByVal(x)); if(opt==4) printf("%d\n",a.GetValByRank(x)); if(opt==5) printf("%d\n",a.GetValByRank(a.GetRankByVal(x)-1)); if(opt==6) printf("%d\n",a.GetValByRank(a.GetRankByVal(x+1))); } }