牛客练习赛6 B.点权和 思维题

原题链接:https://ac.nowcoder.com/acm/contest/26/B

题意

在这里插入图片描述

分析

n个点,m次询问,m的范围是1e7,因此直接暴力的方法直接t飞。其实我们发现一个点的答案,影响他的因素只有三个,他自身的操作数,他父节点的操作数和他子节点的操作数,因此我们只需要设三个a[x], b[x], c[x]分别表示x节点的操作次数和x子节点的操作次数和x孙子节点的操作次数

接下来我们每次询问的x,答案的贡献来自

  1. 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]
  2. 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]]]
  3. 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;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值