[TYVJ1728/BZOJ3224]普通平衡树-替罪羊树
Posted SkyLYnf
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[TYVJ1728/BZOJ3224]普通平衡树-替罪羊树相关的知识,希望对你有一定的参考价值。
Problem 普通平衡树
Solution
本题是裸的二叉平衡树。有很多种方法可以实现。这里打的是替罪羊树模板。
此题极其恶心。
前驱后继模块需要利用到rank模块来换一种思路求。
很多细节的地方容易炸。我拿数据调了很久才A。
(delt()删除模块其实是不需要重建的,不影响时间复杂度)
替罪羊树具体详见此篇知乎:替罪羊树
AC Code
1 #include "iostream" 2 #include "cstdio" 3 #define alpha 0.7 4 using namespace std; 5 struct ScapeGoatTree{ 6 int lc,rc,n,w,s,fa; 7 }a[100010]; 8 struct REbuild{ 9 int n,w; 10 }d[100010]; 11 void rebuild(int p); 12 int tot=1,tott=0,top=0,h[100010],n,T,X,root; 13 int check(int p){ 14 if(a[p].w==0)return 0; 15 if ((a[a[p].lc].s+a[a[p].lc].w>=double(alpha*(a[p].w+a[p].s)))|| 16 (a[a[p].rc].s+a[a[p].rc].w>=double(alpha*(a[p].w+a[p].s))))return 1; 17 return 0; 18 } 19 int getN(int x){ 20 int now=root; 21 while(a[now].n!=x&&a[now].s!=0){ 22 if(a[now].n>=x)now=a[now].lc; 23 else now=a[now].rc; 24 } 25 return now; 26 } 27 void insr(int x,bool rb){ 28 if(root==0){ 29 root=1; 30 a[1].n=x; 31 a[1].w++; 32 return; 33 } 34 int now=root; 35 while(a[now].s!=0){ 36 if(x==a[now].n){ 37 a[now].w++; 38 return; 39 } 40 if(x>a[now].n&&a[now].rc==0)break; 41 if(x<a[now].n&&a[now].lc==0)break; 42 a[now].s++; 43 if(x>a[now].n)now=a[now].rc; 44 else if(x<a[now].n)now=a[now].lc; 45 } 46 47 if(x==a[now].n){ 48 a[now].w++; 49 return; 50 } 51 a[now].s++; 52 int tmp=now; 53 if(x>a[now].n)now=a[now].rc=++tot; 54 else if(x<a[now].n)now=a[now].lc=++tot; 55 a[now].w++; 56 a[now].n=x; 57 if(tmp!=now)a[now].fa=tmp; 58 int chk=0; 59 while(now!=root){ 60 now=a[now].fa; 61 if(check(now))chk=now; 62 } 63 if(rb)rebuild(chk); 64 } 65 int getnewp(){ 66 if(top>0){ 67 top--; 68 return h[top+1]; 69 } 70 else return ++tot; 71 } 72 void dfs(int p){ 73 h[++top]=p; 74 if(a[p].lc!=0)dfs(a[p].lc); 75 if(a[p].w!=0)d[++tott].n=a[p].n, 76 d[tott].w=a[p].w; 77 a[p].s=0; 78 if(a[p].rc!=0)dfs(a[p].rc); 79 } 80 void make(int l,int r,int p,int fa){ 81 int mid=(l+r)/2; 82 a[p].fa=fa; 83 a[p].w=d[mid].w; 84 a[p].n=d[mid].n; 85 if(mid-1>=l)a[p].lc=getnewp(),make(l,mid-1,a[p].lc,p);else a[p].lc=0; 86 if(mid+1<=r)a[p].rc=getnewp(),make(mid+1,r,a[p].rc,p);else a[p].rc=0; 87 a[p].s=a[a[p].lc].w+a[a[p].lc].s+a[a[p].rc].w+a[a[p].rc].s; 88 } 89 void rebuild(int p){ 90 if(p==0)return; 91 tott=0; 92 dfs(p); 93 int now=getnewp(); 94 a[now].fa=a[p].fa; 95 if(p==root)root=now; 96 int mid=(1+tott)/2; 97 if(d[mid].n>a[a[p].fa].n)a[a[p].fa].rc=now; 98 else a[a[p].fa].lc=now; 99 make(1,tott,now,a[p].fa); 100 } 101 void delt(int p,bool rb){ 102 a[p].w--; 103 int chk=0; 104 while(p!=root){ 105 p=a[p].fa; 106 a[p].s--; 107 if(check(p))chk=p; 108 } 109 // if(rb)rebuild(chk); 110 } 111 int XgetRk(int x); 112 int RkgetX(int x); 113 int suc(int x){ 114 insr(x+1,0); 115 int tmp=XgetRk(x+1),nx=getN(x+1); 116 delt(nx,0); 117 return RkgetX(tmp); 118 } 119 int pre(int x){ 120 insr(x,0); 121 int tmp=XgetRk(x); 122 delt(getN(x),0); 123 return RkgetX(tmp-1); 124 } 125 int XgetRk(int x){ 126 int p=getN(x),ans; 127 ans=a[a[p].lc].s+a[a[p].lc].w; 128 while(p!=root){ 129 if(a[a[p].fa].rc==p)ans+=a[a[a[p].fa].lc].s+a[a[a[p].fa].lc].w+a[a[p].fa].w; 130 p=a[p].fa; 131 } 132 return ans+1; 133 } 134 int RkgetX(int x){ 135 int now=root; 136 while(true){ 137 int lcS=a[a[now].lc].s+a[a[now].lc].w; 138 if(x<=lcS)now=a[now].lc; 139 else if(x>lcS&&x<=a[now].w+lcS)return a[now].n; 140 else x-=lcS+a[now].w,now=a[now].rc; 141 if(x==0)return a[now].fa; 142 } 143 } 144 int main(){ 145 scanf("%d",&n); 146 for(int i=1;i<=n;i++){ 147 if(i%1000==0){ 148 int ttott; 149 ttott++; 150 } 151 scanf("%d%d",&T,&X); 152 if(T==1)insr(X,1); 153 else if(T==2)delt(getN(X),1); 154 else if(T==3)printf("%d\n",XgetRk(X)); 155 else if(T==4)printf("%d\n",RkgetX(X)); 156 else if(T==5)printf("%d\n",pre(X)); 157 else if(T==6)printf("%d\n",suc(X)); 158 } 159 }
以上是关于[TYVJ1728/BZOJ3224]普通平衡树-替罪羊树的主要内容,如果未能解决你的问题,请参考以下文章
bzoj3224: Tyvj 1728 普通平衡树 treap