版权声明:本文为博主原创文章,转载请附上原博客链接。 https://blog.csdn.net/Dale_zero/article/details/82227569
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6394
题目的数据好像不用先处理dfs序也可以过,将树分块然后每次更新在区间内向后更新,每次询问时向前查找一直到树根为止,同时更新向上弹的次数
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define mod 1000000007
#define For(i,m,n) for(int i=m;i<=n;i++)
#define Dor(i,m,n) for(int i=m;i>=n;i--)
#define LL long long
#define lan(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn=1e5+336;
const int M=333;
int dp[maxn][22];
int a[maxn],b[maxn];
int fa[maxn];
int lg[maxn];
int get(int x,int now)
{
for(int i=0;(1<<i)<=now;i++)
{
if(now&(1<<i))
x=dp[x][i];
}
return x;
}
void update(int x)
{
int t=x*M;
if(!t)
{
t=1;
a[0]=0;
b[0]=0;
}
for(int i=t;i<=x*M+M;i++)
{
if(fa[i]<x*M)
{
a[i]=1;
b[i]=fa[i];
}
else
{
a[i]=a[fa[i]]+1;
b[i]=b[fa[i]];
}
}
}
int query(int x)
{
int ans=0;
while(x)
{
ans+=a[x];
x=b[x];
}
return ans;
}
int main()
{
int sum=2;
lg[1]=0;
for(int i=1;i<maxn;i++)
{
lg[i]=lg[i-1];
if(i>sum)
{
sum<<=1;
lg[i]++;
}
}
int t;
scanf("%d",&t);
while(t--)
{
int n,m;
scanf("%d",&n);
lan(dp,0);
For(i,2,n)
scanf("%d",&dp[i][0]);
// dp[1][0]=1;
For(j,1,lg[n])
For(i,1,n)
dp[i][j]=dp[dp[i][j-1]][j-1];
For(i,1,n)
{
int tem;
scanf("%d",&tem);
fa[i]=get(i,tem);
}
for(int i=0;i<=n/M;i++)
update(i);
// For(i,1,n)
// printf("a%d=%d b%d=%d fa%d=%d\n",i,a[i],i,b[i],i,fa[i]);
scanf("%d",&m);
int op,p,q;
while(m--)
{
scanf("%d",&op);
if(op==1)
{
scanf("%d",&p);
printf("%d\n",query(p));
}
else if(op==2)
{
scanf("%d%d",&p,&q);
fa[p]=get(p,q);
update(p/M);
}
}
}
return 0;
}