zoukankan      html  css  js  c++  java
  • NC14393 点权和(思维)

    这种题肯定不会是暴力枚举,多半考虑是贡献

    首先我们要想清楚的是,我每次操作,会对哪些节点产生影响,答案又是从哪些节点更新而来

    很显然我们会从儿子,自身,父亲这三个角度去思考问题。

    所以我们会设计状态 now[]表示自身被操作的次数,a[],表示被儿子影响的次数,b[]表示的是被孙子操作的次数,in[]表示的是儿子个数。

    为什么这里会出现孙子呢,因为孙子+1,儿子+1,那么当答案的时候,儿子的值变化了,所以答案也变化了。

    为什么不用专门设计父亲呢?因为所有的父亲都是别人的儿子,所以这样的状态足以,不然就更加复杂了。

    假如我们对当前点进行更新,那么我们可以更新:

    当前点的权值,别的点的儿子影响,孙子影响。

    具体解释看代码,很多不同的答案都是对的,只要能表达清楚就行

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cstdio>
    #include<map>
    using namespace std;
    typedef long long ll;
    const int N=1e5+5;
    const int mod=19260817;
    ll p[N],a[N],b[N];
    ll in[N];
    ll now[N];
    int main(){
        int n,m;
        cin>>n>>m;
        int i;
        for(i=2;i<=n;i++){
            int x;
            scanf("%d",&x);
            in[x]++;
            p[i]=x;
        }
        ll res=0;
        for(i=1;i<=m;i++){
            int x;
            scanf("%d",&x);
            now[x]++;//当前操作+1
            ll ans=0;
            if(p[x]){
                ll t=p[x];
                a[t]++;//父亲被自己影响+1
                ans=(ans+now[t]*2ll+a[t])%mod;//父亲的操作要×2,因为父亲和自己都加了1,再加上父亲被自己影响的次数
            }
            if(p[p[x]]){
                ll t=p[p[x]];
                ans=(ans+now[t])%mod;//爷爷的操作影响
                b[t]++;//爷爷被自己的影响
            }
            ans=(ans+(in[x]+1)%mod*now[x]%mod+a[x]*2+b[x])%mod;//自己操作数的贡献,以及儿子对儿子和自己的贡献以及孙子的贡献
            res=(res+ans*i+mod)%mod;
        }
        cout<<res<<endl;
        return 0;
    }
    View Code
  • 相关阅读:
    01_15_Struts2_带参数的结果集
    Splunk_导航菜单配置
    质量管理体系框架
    测试人员和测试Leader考核维度
    作为管理者口袋里面需要有多把武器,拿来即用
    产品质量体系——如何度量产品质量?
    adb 获取平台号
    模拟定位工具gps mock
    Android 电脑投屏工具Vysor Pro介绍
    Eclipse+Maven+TestNg+ReportNg 生成测试报告
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/12683783.html
Copyright © 2011-2022 走看看