【每日一题】 点权和
点权和
https://ac.nowcoder.com/acm/problem/14393
点权和
解题思路:我们统计每个结点的时候,需要考虑自己本身的贡献、自己父亲的贡献以及自己儿子的贡献
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;
} 

