蒜头君的树

来源:互联网 发布:江苏凤凰数据有限公司 编辑:程序博客网 时间:2024/05/16 18:35

蒜头君的树

题解

先存图,再dfs,dfs的过程中统计以x点为子树的点的总数cnt[x],这样可以求出来x和fa[x]连的这条边一共被使用了(n-cnt[x])*cnt[x]次
再求出来最短路之和tot(因为是树,所以最短路好求),对于每次修改,只需要将将差乘上使用次数就好了

#include<iostream>#include<cstdio>using namespace std;long long x,n,y,fa[1000001],m,e,head[1000001],cnt[100001],dis[100001];long long tot;struct node{long long from,to,cost,nxt;}a[1000001];void add(long long f,long long t,long long w){    e++;    a[e].to=t;    a[e].from=f;    a[e].cost=w;    a[e].nxt=head[f];    head[f]=e;}void dfs(long long x){    for(long long i=head[x];i;i=a[i].nxt)    {        long long t=a[i].to;        if(t!=fa[x])        {            dfs(t);            cnt[x]+=cnt[t];            tot+=(n-cnt[t])*cnt[t]*a[i].cost;        }    }    cnt[x]++;}int main(){//  freopen("1.txt","r",stdin);    cin>>n;fa[1]=1;    for(long long i=1;i<=n-1;i++)    {        scanf("%lld%lld",&x,&dis[i+1]);        fa[i+1]=x;        add(i+1,x,dis[i+1]);        add(x,i+1,dis[i+1]);    }    dfs(1);    printf("%lld\n",tot);    cin>>m;    for(long long i=1;i<=m;i++)    {        scanf("%lld%lld",&x,&y);        tot+=(y-dis[x])*cnt[x]*(n-cnt[x]);        dis[x]=y;        printf("%lld\n",tot);    }}

吧啦吧啦吧啦吧啦吧啦吧啦吧啦吧啦吧啦

原创粉丝点击