码迷,mamicode.com
首页 > 其他好文 > 详细

2018.12.29-dtoj-3626

时间:2018-12-30 13:58:28      阅读:212      评论:0      收藏:0      [点我收藏+]

标签:read   closed   cli   dep   bit   har   col   pen   view   

题目描述:

有一棵N个节点的树, 令d(i,j)为i到j经过的边的条数。有M个炸弹, 第i个炸弹在节点posi上, 威力为power i,它会对所有节点j造成max(0,power i−d(posi,j))的伤害。
求出每个节点最终受到的伤害。

算法标签:点分治

思路:

考虑对于每次求点,仅求以当前重心为根时,不同子树之间的贡献。每次处理出炸弹到根的距离和每个点到根距离,我们会发现对于在同一个子树的答案我们会多算,所以再对每个子树单独做一次,减去多算的答案。

以下代码:

技术分享图片
#include<bits/stdc++.h>
#define il inline
#define LL long long
#define _(d) while(d(isdigit(ch=getchar())))
using namespace std;
const int N=2e5+5,M=5e5+5;
int sz[N],d[N],son[N],rt,size,md,A[N],tt,num[N];bool vis[N];
int n,m,head[N],ne[N<<1],to[N<<1],cnt,hd[N],val[M],nx[M],tot;LL res[N],sum[N];
il int read(){int x;char ch;_(!);x=ch^48;_()x=(x<<1)+(x<<3)+(ch^48);return x;}
il void insert(int x,int y){ne[++cnt]=head[x];head[x]=cnt;to[cnt]=y;}
il void ins(int x,int y){nx[++tot]=hd[x];hd[x]=tot;val[tot]=y;}
il void getrt(int x,int fa){
    son[x]=sz[x]=1;
    for(int i=head[x];i;i=ne[i]){
        if(fa==to[i]||vis[x])continue;
        getrt(to[i],x);sz[x]+=sz[to[i]];
        son[x]=max(son[x],sz[to[i]]);
    }
    son[x]=max(son[x],size-sz[x]);
    if(son[x]<son[rt])rt=x;
}
il void getmd(int x,int fa){
    if(d[x]>md)md=d[x];A[++tt]=x;
    for(int i=head[x];i;i=ne[i]){
        if(fa==to[i]||vis[to[i]])continue;
        d[to[i]]=d[x]+1;getmd(to[i],x);
    }
}
il void dfs(int x,int fa){
    for(int i=hd[x];i;i=nx[i]){
        int v=min(val[i]-d[x],md);
        if(v>0)sum[v]+=val[i]-d[x],num[v]++;
    }
    for(int i=head[x];i;i=ne[i]){
        if(fa==to[i]||vis[to[i]])continue;
        dfs(to[i],x);
    }
}
il void work(int x,int dep,int f){
    tt=md=0;d[x]=dep;getmd(x,0);md++;
    for(int i=0;i<=md;i++)sum[i]=0,num[i]=0;
    dfs(x,0);
    for(int i=1;i<=md;i++)sum[i]+=sum[i-1],num[i]+=num[i-1];
    for(int i=1;i<=tt;i++){
        int u=A[i];
        res[u]+=1ll*(sum[md]-sum[d[u]]-1ll*d[u]*(num[md]-num[d[u]]))*f;
    }
}
il void solve(int x){
    vis[x]=1;work(x,0,1);
    for(int i=head[x];i;i=ne[i]){
        if(vis[to[i]])continue;
        work(to[i],1,-1);
    }
    for(int i=head[x];i;i=ne[i]){
        if(vis[to[i]])continue;
        rt=0;getrt(to[i],x);solve(rt);
    }
}
int main()
{
    n=read();m=read();
    for(int i=2;i<=n;i++){int x=read();insert(i,x);insert(x,i);}
    for(int i=1;i<=m;i++){int x=read(),y=read();ins(x,y);}
    size=n;son[0]=n;getrt(1,0);solve(rt);
    for(int i=1;i<=n;i++)printf("%lld\n",res[i]);
    return 0;
}
View Code

 

2018.12.29-dtoj-3626

标签:read   closed   cli   dep   bit   har   col   pen   view   

原文地址:https://www.cnblogs.com/Jessie-/p/10199129.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!