题面:
Cut the tree
Description
给一个具有 N 个节点的有根树,以 1 号节点为根,节点编号从 1 开始,点有点权。
树的第 H 层权值为深度为 H 的所有点的点权之和。
树的总权值为所有层权值的最大值。
问分别割掉以 1,2,…,N 为根的子树后,剩余树的总权值为多少。
Input
第一行输入一个正整数 N 表示节点的个数。(2 <= N <= 100000)
接下来 N-1 行每行两个正整数 x , y,表示节点 x 和节点 y 之间有边。
最后一行输入N个正整数,v1,v2,…,vn 分别表示每个节点的点权。(1 <= vi <= 1000000000)
Output
输出 N 个整数,分别表示割掉以 1,2,…,N 为根的子树后,剩余树的总权值。
Sample
Input
6
2 4
3 4
4 1
5 1
6 5
3 7 6 1 4 5
Output
0 11 12 5 13 13
题解:
树上启发式合并,同时用线段树维护最大值。
这个解法是两个log的,只能过简单版本,难度较大的版本过不去。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
#include<queue>
#include<bitset>
#include<map>
#include<set>
#define ll long long
#define pr make_pair
#define pb push_back
#define ui unsigned int
#define lc (cnt<<1)
#define rc (cnt<<1|1)
using namespace std;
const int inf=0x3f3f3f3f;
const ll lnf=0x3f3f3f3f3f3f3f3f;
const int mod=1000000007;
const double eps=1e-8;
const double dnf=1e20;
const double pi=acos(-1.0);
const int maxn=100100;
const int up=100;
const int maxp=1100;
struct node
{
int l,r;
ll maxx;
}t[maxn<<2];
int c[maxn];
ll cval[maxn];
void pushup(int cnt)
{
t[cnt].maxx=max(t[lc].maxx,t[rc].maxx);
}
void build(int l,int r,int cnt)
{
t[cnt].l=l,t[cnt].r=r;
t[cnt].maxx=0;
if(l==r)
{
t[cnt].maxx=cval[l];
return ;
}
int mid=(l+r)>>1;
build(l,mid,lc);
build(mid+1,r,rc);
pushup(cnt);
}
void change(int pos,int cnt,int val)
{
if(t[cnt].l==t[cnt].r)
{
t[cnt].maxx+=val;
return ;
}
if(pos<=t[lc].r) change(pos,lc,val);
else change(pos,rc,val);
pushup(cnt);
}
int head[maxn],ver[maxn<<1],nt[maxn<<1],tot=1;
int si[maxn],son[maxn],n;
int q[maxn],maxx;
ll val[maxn];
void add(int x,int y)
{
ver[++tot]=y,nt[tot]=head[x],head[x]=tot;
}
void bfs(int s)
{
int l=1,r=1;
maxx=1;
q[1]=s;
c[s]=1;
cval[c[s]]+=val[s];
while(l<=r)
{
int x=q[l++];
for(int i=head[x];i;i=nt[i])
{
int y=ver[i];
if(c[y]) continue;
c[y]=c[x]+1;
maxx=max(maxx,c[y]);
cval[c[y]]+=val[y];
q[++r]=y;
}
}
}
void dfs1(int x,int fa)
{
int maxson=0;
si[x]=1;
for(int i=head[x];i;i=nt[i])
{
int y=ver[i];
if(y==fa) continue;
dfs1(y,x);
si[x]+=si[y];
if(si[y]>maxson) maxson=si[y],son[x]=y;
}
}
ll ans[maxn];
int hson=0;
void in(int x,int fa,int f)
{
change(c[x],1,val[x]*f);
for(int i=head[x];i;i=nt[i])
{
int y=ver[i];
if(y==fa||y==hson) continue;
in(y,x,f);
}
}
void dfs2(int x,int fa,int flag)
{
for(int i=head[x];i;i=nt[i])
{
int y=ver[i];
if(y==fa||y==son[x]) continue;
dfs2(y,x,0);
}
if(son[x])
{
dfs2(son[x],x,1);
hson=son[x];
}
in(x,fa,-1);
ans[x]=t[1].maxx;
hson=0;
if(!flag) in(x,fa,1);
}
int main(void)
{
scanf("%d",&n);
int x,y;
for(int i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
for(int i=1;i<=n;i++)
scanf("%lld",&val[i]);
bfs(1);
build(1,maxx,1);
dfs1(1,0);
dfs2(1,0,0);
for(int i=1;i<=n;i++)
{
if(i!=1)putchar(' ');
printf("%lld",ans[i]);
}
putchar('\n');
return 0;
}