[USACO12FEB]附近的牛Nearby Cows
水题
19:46开始看题,20:09AC
就是大力dp啊,设dp[i][j]表示考虑到第i个点,距离它为j的数量,第一次倒推,求出子树中的,第二次正推,从父节点转移
转移见代码
// luogu-judger-enable-o2
#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<set>
#include<map>
#include<vector>
#define maxn 400006
#define int long long
#define SZJ signed
#include<time.h>
#define AK main
#define half (l+r)>>1
#define SDOI ()
#define mod 19650827
using namespace std;
#define rep(i,a,b) for (int (i)=(a);i<=(b);++(i))
#define dep(i,a,b) for (int (i)=(a);i>=(b);--(i))
#define erep(i,a) for (int (i)=head[(a)];(i)!=-1;(i)=e[(i)].next)
#define lson t[s].lc
#define rson t[s].rc
#define MP make_pair
int head[maxn],cur,n,k,dp[maxn][25],size[maxn],val[maxn];
struct hzw
{
int to,next;
}e[maxn];
inline void add(int a,int b)
{
e[cur].to=b;
e[cur].next=head[a];
head[a]=cur++;
}
inline void dfs(int s,int fa)
{
size[s]=1;
dp[s][0]=val[s];
erep(i,s)
{
if (e[i].to==fa) continue;
dfs(e[i].to,s);
size[s]+=size[e[i].to];
rep(j,1,k) dp[s][j]+=dp[e[i].to][j-1];
}
}
int bef[25];
inline void dfs2(int s,int fa)
{
if (s!=1)
{
rep(i,0,k) bef[i]=dp[s][i];
dp[s][1]+=val[fa];
rep(i,2,k)
{
dp[s][i]+=dp[fa][i-1];
dp[s][i]-=bef[i-2];
}
}
erep(i,s)
{
if (e[i].to==fa) continue;
dfs2(e[i].to,s);
}
}
int fina[maxn];
SZJ AK SDOI
{
memset(head,-1,sizeof(head));
cin>>n>>k;
rep(i,1,n-1)
{
int a,b;
scanf("%lld%lld",&a,&b);
add(a,b);
add(b,a);
}
rep(i,1,n) scanf("%lld",&val[i]);
dfs(1,1);
dfs2(1,1);
rep(i,1,n) rep(j,0,k) fina[i]+=dp[i][j];
rep(i,1,n) printf("%lld\n",fina[i]);
}