原题链接:https://ac.nowcoder.com/acm/contest/26/B
题意
分析
n个点,m次询问,m的范围是1e7,因此直接暴力的方法直接t飞。其实我们发现一个点的答案,影响他的因素只有三个,他自身的操作数,他父节点的操作数和他子节点的操作数,因此我们只需要设三个a[x], b[x], c[x]分别表示x节点的操作次数和x子节点的操作次数和x孙子节点的操作次数
接下来我们每次询问的x,答案的贡献来自
- x 的 权 值 = a [ x ] + a [ f a [ x ] ] + b [ x ] x的权值 = a[x] + a[fa[x]] +b[x] x的权值=a[x]+a[fa[x]]+b[x]
- x 的 父 节 点 的 权 值 = a [ f a [ x ] ] + b [ f a [ x ] ] + a [ f a [ f a [ x ] ] ] x的父节点的权值 = a[fa[x]] + b[fa[x]] + a[fa[fa[x]]] x的父节点的权值=a[fa[x]]+b[fa[x]]+a[fa[fa[x]]]
- x 的 子 节 点 的 权 值 和 = a [ x ] ∗ s z [ x ] + c [ x ] + b [ x ] x的子节点的权值和 = a[x] * sz[x] + c[x] + b[x] x的子节点的权值和=a[x]∗sz[x]+c[x]+b[x]
Code
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define re register
typedef long long ll;
typedef pair<ll, ll> PII;
typedef unsigned long long ull;
const int N = 1e6 + 10, M = 1e6 + 5, INF = 0x3f3f3f3f;
const int MOD = 19260817;
ll sz[N], a[N], b[N], c[N];
int fa[N];
void solve() {
int n, m; cin >> n >> m;
for (int i = 2; i <= n; i++) {
cin >> fa[i];
sz[fa[i]]++;
}
ll hash = 0;
for (int i = 1; i <= m; i++) {
int x; cin >> x;
a[x]++;
if (fa[x]) b[fa[x]]++;
if (fa[fa[x]]) c[fa[fa[x]]]++;
ll tmp1 = (a[x] + b[x] + a[fa[x]]) % MOD;//自身
ll tmp2 = (a[fa[x]] + b[fa[x]] + a[fa[fa[x]]]) % MOD;//父节点
ll tmp3 = (a[x] * sz[x] + b[x] + c[x]) % MOD; //子节点
hash = (hash + (tmp1 + tmp2 + tmp3) % MOD * i % MOD % MOD) % MOD;
}
cout << hash << endl;
}
signed main() {
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
#ifdef ACM_LOCAL
freopen("input", "r", stdin);
freopen("output", "w", stdout);
#endif
solve();
return 0;
}