Tree CodeForces -932D
错误记录:如下注释语句
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 typedef long long LL; 5 LL log2n=19,cnt=1; 6 LL anc[400010][20],maxv[400010][20],v[400010]; 7 LL anc2[400010][20],sum[400010][20]; 8 LL pow2[]={1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288}; 9 //maxv[i][j]指i到其2^j级祖先的路径上点权最大值,含2^j级祖先,不含i 10 //sum[i][j]指i到其2^j级祖先的路径上点权之和,含祖先,不含i 11 LL Q,last; 12 int main() 13 { 14 LL i,idx,p,q,t,ans; 15 v[0]=1e15+1; 16 for(i=0;i<=log2n;i++) maxv[1][i]=maxv[0][i]=sum[1][i]=sum[0][i]=1e15+1; 17 scanf("%lld",&Q); 18 while(Q--) 19 { 20 scanf("%lld%lld%lld",&idx,&p,&q); 21 p^=last;q^=last; 22 //printf("%lld %lld\n",p,q); 23 if(idx==1) 24 { 25 v[++cnt]=q;anc[cnt][0]=p;maxv[cnt][0]=v[anc[cnt][0]]; 26 //putchar('a');printf("%d %d ",0,maxv[cnt][0]); 27 for(i=1;i<=log2n;i++) 28 { 29 anc[cnt][i]=anc[anc[cnt][i-1]][i-1]; 30 maxv[cnt][i]=max(maxv[cnt][i-1],maxv[anc[cnt][i-1]][i-1]); 31 //printf("%d %d ",i,maxv[cnt][i]); 32 } 33 //putchar('b'); 34 for(t=cnt,i=log2n;i>=0;i--) 35 if(maxv[t][i]<v[cnt]) 36 t=anc[t][i]; 37 anc2[cnt][0]=anc[t][0];sum[cnt][0]=v[anc2[cnt][0]]; 38 //printf("%d %d\n",cnt,nxt[cnt]); 39 //printf("%lld %lld ",0LL,sum[cnt][0]); 40 for(i=1;i<=log2n;i++) 41 { 42 anc2[cnt][i]=anc2[anc2[cnt][i-1]][i-1]; 43 sum[cnt][i]=sum[cnt][i-1]+sum[anc2[cnt][i-1]][i-1]; 44 //printf("%lld %lld ",i,sum[cnt][i]); 45 } 46 //putchar('c'); 47 } 48 else 49 { 50 q-=v[p];ans=1;if(q<0){ans=0;goto xxx;} 51 for(t=p,i=log2n;i>=0;i--) 52 if(sum[t][i]<=q) 53 { 54 //t=anc2[t][i]; 55 q-=sum[t][i];ans+=pow2[i];//ans++ 56 t=anc2[t][i]; 57 } 58 xxx:last=ans; 59 printf("%lld\n",ans); 60 } 61 } 62 return 0; 63 }
对于原树,每加入一个节点u求出maxv(含义见程序),然后由这个新节点u向上倍增找到其祖先节点v,使得u到v的路径上所有点(不含u,含v)权值的最大值小于u的权值,且v深度最小。那么v的父节点就是u向上一级一级跳时第一个能访问到的权值大于等于u的节点,记为nxt[u](程序中省略,直接记为anc2[u][0])。
这样子,对于每个节点u(除了1号)都能得到nxt[u],把nxt[u]当做u的父节点,形成一棵新的树,那么查询转化为给定一个节点u,在新树上找到u的祖先节点v,使得u到v的路径上所有点(含u和v)权值之和小于等于x,且v的深度最小,输出u到v的路径上点数(含u和v)。(当然也可能u的权值就超过x了,那么输出0,要特判)。仍然倍增解决即可。
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 typedef long long LL; 5 LL log2n=19,cnt=1; 6 LL anc[400010][20],maxv[400010][20],v[400010]; 7 LL anc2[400010][20],sum[400010][20]; 8 //maxv[i][j]指i到其2^j级祖先的路径上点权最大值,含2^j级祖先,不含i 9 //sum[i][j]指i到其2^j级祖先的路径上点权之和,含祖先,不含i 10 LL Q,last; 11 int main() 12 { 13 LL i,idx,p,q,t,ans; 14 v[0]=1e15+1; 15 for(i=0;i<=log2n;i++) maxv[1][i]=maxv[0][i]=sum[1][i]=sum[0][i]=1e15+1; 16 scanf("%lld",&Q); 17 while(Q--) 18 { 19 scanf("%lld%lld%lld",&idx,&p,&q); 20 p^=last;q^=last; 21 if(idx==1) 22 { 23 v[++cnt]=q;anc[cnt][0]=p;maxv[cnt][0]=v[anc[cnt][0]]; 24 for(i=1;i<=log2n;i++) 25 { 26 anc[cnt][i]=anc[anc[cnt][i-1]][i-1]; 27 maxv[cnt][i]=max(maxv[cnt][i-1],maxv[anc[cnt][i-1]][i-1]); 28 } 29 for(t=cnt,i=log2n;i>=0;i--) 30 if(maxv[t][i]<v[cnt]) 31 t=anc[t][i]; 32 anc2[cnt][0]=anc[t][0];sum[cnt][0]=v[anc2[cnt][0]]; 33 for(i=1;i<=log2n;i++) 34 { 35 anc2[cnt][i]=anc2[anc2[cnt][i-1]][i-1]; 36 sum[cnt][i]=sum[cnt][i-1]+sum[anc2[cnt][i-1]][i-1]; 37 } 38 } 39 else 40 { 41 q-=v[p];ans=1;if(q<0){ans=0;goto xxx;} 42 for(t=p,i=log2n;i>=0;i--) 43 if(sum[t][i]<=q) 44 { 45 q-=sum[t][i];ans+=(1LL<<i); 46 t=anc2[t][i]; 47 } 48 xxx:last=ans; 49 printf("%lld\n",ans); 50 } 51 } 52 return 0; 53 }