替罪羊树—BZOJ3224: Tyvj 1728 普通平衡树
冬令营被平衡树坑了之后,打算苦练一番数据结构(QAQ)。
先是打了一下想学好久的替罪羊树。
替罪羊树实现方法很简单,就是在不满足平衡条件的时候暴力重构子树。
调试小结:
1.删除操作分两类情况:如果某点只有一个孩子,将它的孩子提上来即可,否则将它变为它的前驱,再删去它的前驱。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 const double a=0.75; 7 inline int getnum() 8 { 9 int ans=0,fh=1;char ch=getchar(); 10 while(ch<'0'||ch>'9'){if(ch=='-')fh*=-1;ch=getchar();} 11 while(ch>='0'&&ch<='9')ans=ans*10+ch-'0',ch=getchar(); 12 return fh*ans; 13 } 14 struct node{int s[2],f,size,num;}t[2100000];int tnum,root; 15 inline void init() 16 { 17 tnum=2;root=1; 18 t[1].num=-2147483647;t[1].size=2;t[1].s[1]=2; 19 t[2].num=2147483647;t[2].size=1;t[2].f=1; 20 } 21 inline bool balance(int po) 22 { 23 return (double)t[po].size*a>=(double)t[t[po].s[0]].size 24 &&(double)t[po].size*a>=(double)t[t[po].s[1]].size; 25 } 26 int E[210000],esize; 27 void travel(int po) 28 { 29 if(t[po].s[0])travel(t[po].s[0]); 30 E[++esize]=po; 31 if(t[po].s[1])travel(t[po].s[1]); 32 } 33 int build(int l,int r) 34 { 35 if(l>r)return 0; 36 int mid=(l+r)/2,po=E[mid]; 37 t[t[po].s[0]=build(l,mid-1)].f=po; 38 t[t[po].s[1]=build(mid+1,r)].f=po; 39 t[po].size=t[t[po].s[0]].size+t[t[po].s[1]].size+1; 40 return po; 41 } 42 inline void rebuild(int po) 43 { 44 esize=0;travel(po); 45 int fa=t[po].f,ws=(t[t[po].f].s[1]==po); 46 int npo=build(1,esize); 47 t[t[fa].s[ws]=npo].f=fa; 48 if(po==root)root=npo; 49 } 50 inline void insert(int num) 51 { 52 int now=root,npo=++tnum; 53 t[npo].size=1;t[npo].num=num; 54 while(true) 55 { 56 t[now].size++; 57 bool ws=(num>=t[now].num); 58 if(t[now].s[ws])now=t[now].s[ws]; 59 else {t[t[now].s[ws]=npo].f=now;break ;} 60 } 61 int inv=0; 62 for(int i=npo;i;i=t[i].f)if(!balance(i))inv=i; 63 if(inv)rebuild(inv); 64 } 65 inline int rank(int num) 66 { 67 int now=root,ans=0; 68 while(now) 69 { 70 if(t[now].num<num)ans+=t[t[now].s[0]].size+1,now=t[now].s[1]; 71 else now=t[now].s[0]; 72 } 73 return ans; 74 } 75 inline int getkth(int kth) 76 { 77 int now=root; 78 while(true) 79 { 80 if(t[t[now].s[0]].size==kth-1)return now; 81 else if(t[t[now].s[0]].size>=kth)now=t[now].s[0]; 82 else kth-=t[t[now].s[0]].size+1,now=t[now].s[1]; 83 } 84 return now; 85 } 86 inline int getn(int num) 87 { 88 int now=root; 89 while(true) 90 { 91 if(t[now].num==num)return now; 92 else now=t[now].s[t[now].num<num]; 93 } 94 } 95 inline void erase(int po) 96 { 97 if(t[po].s[0]&&t[po].s[1]) 98 { 99 int tpo=t[po].s[0]; 100 while(t[tpo].s[1])tpo=t[tpo].s[1]; 101 t[po].num=t[tpo].num; 102 po=tpo; 103 } 104 int son=(t[po].s[0])?t[po].s[0]:t[po].s[1],ws=(t[t[po].f].s[1]==po); 105 t[t[t[po].f].s[ws]=son].f=t[po].f; 106 for(int i=t[po].f;i;i=t[i].f)t[i].size--; 107 if(po==root)root=son; 108 } 109 inline int succ(int num) 110 { 111 int now=root,ans=2147483647; 112 while(now) 113 { 114 if(t[now].num>num)ans=min(ans,t[now].num),now=t[now].s[0]; 115 else now=t[now].s[1]; 116 } 117 return ans; 118 } 119 inline int pred(int num) 120 { 121 int now=root,ans=-2147483647; 122 while(now) 123 { 124 if(t[now].num<num)ans=max(ans,t[now].num),now=t[now].s[1]; 125 else now=t[now].s[0]; 126 } 127 return ans; 128 } 129 int main(int argc, char *argv[]) 130 { 131 init(); 132 int n=getnum(); 133 for(int i=1;i<=n;i++) 134 { 135 int p=getnum(),num=getnum(); 136 if(p==1)insert(num); 137 if(p==2)erase(getn(num)); 138 if(p==3)printf("%d\n",rank(num)); 139 if(p==4)printf("%d\n",t[getkth(num+1)].num); 140 if(p==5)printf("%d\n",pred(num)); 141 if(p==6)printf("%d\n",succ(num)); 142 } 143 return 0; 144 }