AB略
C
最大值最小考虑二分答案,还有就是本题对n个格子涂色的检验难度很小
D
num[i]表示以这个点结尾能形成的路线数,dis[i]表示以深度为i的点结尾能形成的路线数,由此推出:num[i]=dis[d[i]-1]-num[fa[i]],dis累加即可,特殊处理深度为1和2的点。需要注意的是,每一步加法操作都需要取模,而减法操作如果出现负数,需+mod
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=3e5+10,mod=998244353;
int T,n,num[N],p[N],dis[N],ans;
int ver[N],Next[N],head[N],tot;
struct node{
int d,id;
}a[N];
void init()
{
tot=ans=0;
for(int i=1;i<=n;i++)
ver[i]=head[i]=Next[i]=num[i]=dis[i]=0;
}
void add(int x,int y)
{
ver[++tot]=y;
Next[tot]=head[x],head[x]=tot;
}
bool cmp(node x,node y)
{
return x.d<y.d;
}
void dfs(int x,int fa)
{
for(int i=head[x];i;i=Next[i])
{
int y=ver[i];
if(y==fa) continue;
a[y].d=a[x].d+1;
dfs(y,x);
}
}
void solve()
{
cin>>n;
init();
for(int i=2;i<=n;i++)
{
cin>>p[i];
add(p[i],i);
}
for(int i=1;i<=n;i++)
a[i].id=i;
a[1].d=1;
dfs(1,-1);
sort(a+1,a+n+1,cmp);
for(int i=2;i<=n;i++)
{
if(a[i].d>2) break;
num[a[i].id]=1;
dis[2]++;
ans++;
}
ans++;
for(int i=2;i<=n;i++)
{
if(a[i].d<3) continue;
num[a[i].id]=dis[a[i].d-1]-num[p[a[i].id]];
if(num[a[i].id]<0) num[a[i].id]+=mod;
ans=(ans+num[a[i].id])%mod;
dis[a[i].d]=(dis[a[i].d]+num[a[i].id])%mod;
}
cout<<ans<<endl;
}
signed main()
{
std::ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>T;
while(T--) solve();
}