• BZOJ 3727 DP?推式子..


     思路:

    设$sum[i]表示i的子树中a[i]的和$

    $b[1]=Sigma a[i]*dis[i] = Sigma _{i=2} ^n sum[i]$

    $b[x]-b[fa[x]]=sum[1]-2*sum[x]$

    $sum[1]={Sigma_{i=2}^n (b[x]-b[fa[x]])+2*b[1] over n-1}$

    $求出sum[1]以后根据a[x]=sum[x]-Sigma_{v是x的儿子} sum[v]带入求出其它值即可$

    $复杂度O(n)$

    //By SiriusRen
    #include <cstdio>
    #include <cstring>
    using namespace std;
    #define int long long
    const int N=600500;
    int n,xx,yy,first[N],next[N],v[N],tot,fa[N],rev[N],cnt,b[N],X;
    long long sum[N],ans[N];
    void add(int x,int y){v[tot]=y,next[tot]=first[x],first[x]=tot++;}
    void dfs(int x){
        rev[++cnt]=x;
        for(int i=first[x];~i;i=next[i])if(v[i]!=fa[x])
            fa[v[i]]=x,dfs(v[i]);
    }
    void dfs2(int x){
        ans[x]=sum[x];
        for(int i=first[x];~i;i=next[i])if(v[i]!=fa[x])
            dfs2(v[i]),ans[x]-=sum[v[i]];
    }
    signed main(){
        memset(first,-1,sizeof(first));
        scanf("%lld",&n);
        for(int i=1;i<n;i++)scanf("%lld%lld",&xx,&yy),add(xx,yy),add(yy,xx);
        for(int i=1;i<=n;i++)scanf("%lld",&b[i]);
        dfs(1);
        for(int i=2;i<=n;i++)sum[1]+=(b[i]-b[fa[i]]);
        sum[1]=(sum[1]+2*b[1])/(n-1);
        for(int i=2;i<=n;i++)X=rev[i],sum[X]=(sum[1]-b[X]+b[fa[X]])/2;
        dfs2(1);
        for(int i=1;i<=n;i++)printf("%lld%c",ans[i],i!=n?' ':'
    ');
    }
  • 相关阅读:
    批处理学习总结之常用命令1
    Delphi常用数据类型
    Delphi预编译指令总结
    Delphi同步互斥总结
    MyEclipse 环境配置总结
    倒排索引
    laravel 学习相关笔记
    elasticsearch倒排索引原理
    原生sql和 TP sql怎么关联?
    elastic
  • 原文地址:https://www.cnblogs.com/SiriusRen/p/6667250.html
Copyright © 2020-2023  润新知