点权和

解题思路:我们统计每个结点的时候,需要考虑自己本身的贡献、自己父亲的贡献以及自己儿子的贡献
1.自己的贡献:由自己操作的次数和父亲操作的次数和儿子操作的次数构成
2.父亲的贡献:由自己操作的次数和父亲操作的次数和父亲的父亲操作的次数
3.儿子的贡献:由自己的操作次数*孩子的个数和他儿子+1的次数和他孙子+1的次数构成
接下来就是如何进行上述的求解
我们可以用三个数组分别表示自己的操作次数、自己的儿子操作的次数、自己的孙子操作的次数(a[x],b[x],c[x])
每次操作都要使a[x]++,同时再使得b[fa[x]]++,同时使得c[fa[fa[x]]]++

#include<bits/stdc++.h>
using namespace std;
const int mode=19260817;
const int maxn=1e5+10;
long long sonsize[maxn],a[maxn],b[maxn],c[maxn],fa[maxn];
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i=2;i<=n;i++)
	{
		int x;
		scanf("%d",&x);
		fa[i]=x;
		sonsize[x]++;
	}
	long long ans=0;
	for(int i=1;i<=m;i++)
	{
		int x;
		scanf("%d",&x);
		a[x]++;
		if(fa[x]!=0) b[fa[x]]++;
		if(fa[fa[x]]!=0) c[fa[fa[x]]]++;
		long long f1=(a[fa[x]]+b[fa[x]]+a[fa[fa[x]]])%mode;
		long long f2=(a[x]+a[fa[x]]+b[x])%mode;
		long long f3=(sonsize[x]*a[x]%mode+b[x]+c[x])%mode;
		long long res=(f1+f2+f3)%mode;
		ans=(ans+i*res%mode)%mode;
	}
	printf("%lld\n",ans);
	return 0;
}