错误记录:如下注释语句
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long LL;
LL log2n=,cnt=;
LL anc[][],maxv[][],v[];
LL anc2[][],sum[][];
LL pow2[]={,,,,,,,,,,,,,,,,,,,};
//maxv[i][j]指i到其2^j级祖先的路径上点权最大值,含2^j级祖先,不含i
//sum[i][j]指i到其2^j级祖先的路径上点权之和,含祖先,不含i
LL Q,last;
int main()
{
LL i,idx,p,q,t,ans;
v[]=1e15+;
for(i=;i<=log2n;i++) maxv[][i]=maxv[][i]=sum[][i]=sum[][i]=1e15+;
scanf("%lld",&Q);
while(Q--)
{
scanf("%lld%lld%lld",&idx,&p,&q);
p^=last;q^=last;
//printf("%lld %lld\n",p,q);
if(idx==)
{
v[++cnt]=q;anc[cnt][]=p;maxv[cnt][]=v[anc[cnt][]];
//putchar('a');printf("%d %d ",0,maxv[cnt][0]);
for(i=;i<=log2n;i++)
{
anc[cnt][i]=anc[anc[cnt][i-]][i-];
maxv[cnt][i]=max(maxv[cnt][i-],maxv[anc[cnt][i-]][i-]);
//printf("%d %d ",i,maxv[cnt][i]);
}
//putchar('b');
for(t=cnt,i=log2n;i>=;i--)
if(maxv[t][i]<v[cnt])
t=anc[t][i];
anc2[cnt][]=anc[t][];sum[cnt][]=v[anc2[cnt][]];
//printf("%d %d\n",cnt,nxt[cnt]);
//printf("%lld %lld ",0LL,sum[cnt][0]);
for(i=;i<=log2n;i++)
{
anc2[cnt][i]=anc2[anc2[cnt][i-]][i-];
sum[cnt][i]=sum[cnt][i-]+sum[anc2[cnt][i-]][i-];
//printf("%lld %lld ",i,sum[cnt][i]);
}
//putchar('c');
}
else
{
q-=v[p];ans=;if(q<){ans=;goto xxx;}
for(t=p,i=log2n;i>=;i--)
if(sum[t][i]<=q)
{
//t=anc2[t][i];
q-=sum[t][i];ans+=pow2[i];//ans++
t=anc2[t][i];
}
xxx:last=ans;
printf("%lld\n",ans);
}
}
return ;
}
另外,不能看到要加点就想动态树(不会)什么的,比如这道题,虽然要加点,但是仅此而已,用不到那些东西,只需要加入点时倍增求出要维护的值就行了。
对于原树,每加入一个节点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,要特判)。仍然倍增解决即可。
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long LL;
LL log2n=,cnt=;
LL anc[][],maxv[][],v[];
LL anc2[][],sum[][];
//maxv[i][j]指i到其2^j级祖先的路径上点权最大值,含2^j级祖先,不含i
//sum[i][j]指i到其2^j级祖先的路径上点权之和,含祖先,不含i
LL Q,last;
int main()
{
LL i,idx,p,q,t,ans;
v[]=1e15+;
for(i=;i<=log2n;i++) maxv[][i]=maxv[][i]=sum[][i]=sum[][i]=1e15+;
scanf("%lld",&Q);
while(Q--)
{
scanf("%lld%lld%lld",&idx,&p,&q);
p^=last;q^=last;
if(idx==)
{
v[++cnt]=q;anc[cnt][]=p;maxv[cnt][]=v[anc[cnt][]];
for(i=;i<=log2n;i++)
{
anc[cnt][i]=anc[anc[cnt][i-]][i-];
maxv[cnt][i]=max(maxv[cnt][i-],maxv[anc[cnt][i-]][i-]);
}
for(t=cnt,i=log2n;i>=;i--)
if(maxv[t][i]<v[cnt])
t=anc[t][i];
anc2[cnt][]=anc[t][];sum[cnt][]=v[anc2[cnt][]];
for(i=;i<=log2n;i++)
{
anc2[cnt][i]=anc2[anc2[cnt][i-]][i-];
sum[cnt][i]=sum[cnt][i-]+sum[anc2[cnt][i-]][i-];
}
}
else
{
q-=v[p];ans=;if(q<){ans=;goto xxx;}
for(t=p,i=log2n;i>=;i--)
if(sum[t][i]<=q)
{
q-=sum[t][i];ans+=(1LL<<i);
t=anc2[t][i];
}
xxx:last=ans;
printf("%lld\n",ans);
}
}
return ;
}