题目大意:给一棵树,每次可以选择拿走某个点的所有石子(放到手上),或者在任意一个满足其儿子节点都已经有石子的点
x
x
x放恰好
w
x
w_x
wx个石子。对每个点
x
x
x求恰好在这个位置放
w
x
w_x
wx个石子,一开始手上要有多少石子?
n
≤
1
0
5
n\le10^5
n≤105。
题解:
考虑对每个子树怎么暴力求;
考虑将问题反过来,每次变为若一个点有石子,就在其儿子节点都放上石子,然后把这个点的石子取走。一开始只有根节点有恰好
w
[
r
t
]
w[rt]
w[rt]个石子。
那么考虑一个贪心,我们对每个点维护一个二元组
(
a
,
b
)
(a,b)
(a,b),一开始是
(
−
w
[
x
]
+
∑
y
∈
s
o
n
[
x
]
w
y
,
∑
y
∈
s
o
n
[
x
]
w
y
)
(-w[x]+\sum_{y\in son[x]}w_y,\sum_{y\in son[x]}w_y)
(−w[x]+∑y∈son[x]wy,∑y∈son[x]wy),表示对这个点执行操作会导致目前石子数发生变化的量,和在这个过程中历史增量的最大值。
那么显然
(
a
,
b
)
o
p
e
r
a
t
o
r
(
c
,
d
)
=
(
a
+
c
,
m
a
x
(
b
,
a
+
d
)
)
(a,b)\mathrm{\ operator\ }(c,d)=(a+c,max(b,a+d))
(a,b) operator (c,d)=(a+c,max(b,a+d))
那么我们发现,对于两个二元组
(
a
1
,
b
1
)
,
(
a
2
,
b
2
)
(a_1,b_1),(a_2,b_2)
(a1,b1),(a2,b2)(假设现在石子数发生的变化量是
t
o
t
tot
tot):那么先操作1在操作2,历史增量最大值要对
max
(
b
1
,
a
1
+
b
2
)
\max(b_1,a_1+b_2)
max(b1,a1+b2)取max,否则对
max
(
b
2
,
a
2
+
b
1
)
\max(b_2,a_2+b_1)
max(b2,a2+b1)取max。
因此显然:
1)当
a
1
a_1
a1和
a
2
a_2
a2都
<
0
<0
<0时,
b
1
,
b
2
b_1,b_2
b1,b2才有可能取到max,因此
b
b
b更小的应当早操作。
2)否则若
a
1
a_1
a1和
a
2
a_2
a2一个负一个非负,那么非负的那个优先;
3)否则若
a
1
+
b
2
<
a
2
+
b
1
a_1+b_2<a_2+b_1
a1+b2<a2+b1,则1优先;否则2优先。(等价于
a
−
b
a-b
a−b小的优先)。
那么每次我们操作一个点
x
x
x,若其到根的路径上还有没被操作的点,假设深度最大的是
y
y
y,那么操作完
y
y
y之后就要立刻操作
x
x
x,那么就让
v
a
l
[
y
]
+
=
v
a
l
[
x
]
val[y]+=val[x]
val[y]+=val[x];否则操作
x
x
x。
要把操作序列搞出来,可以用一个可删除堆加上 一个链表加上一个并查集处理出来。
最后发现,一个子树的操作序列,是整棵树的操作序列的子序列,因此搞一个线段树合并即可。
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Rep(i,v) rep(i,0,(int)v.size()-1)
#define lint long long
#define ull unsigned lint
#define db long double
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define gc getchar()
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
typedef pair<int,int> pii;
typedef set<int>::iterator sit;
inline int inn()
{
int x,ch;while((ch=gc)<'0'||ch>'9');
x=ch^'0';while((ch=gc)>='0'&&ch<='9')
x=(x<<1)+(x<<3)+(ch^'0');return x;
}
const int N=200010;
int n,id[N],w[N],fa[N];vector<int> g[N];lint ans[N];
int R[N],tl[N];
struct UF{
int n,fa[N];
inline int init(int _n) { n=_n;rep(i,1,n) fa[i]=i;return 0; }
inline int findf(int x) { return x==fa[x]?x:fa[x]=findf(fa[x]); }
inline int merge(int x,int y) { return x=findf(x),y=findf(y),fa[x]=y; }
}uf;
struct E{
lint a,b;E(lint _a=0,lint _b=0) { a=_a,b=_b; }
inline E operator+(const E &n)const { return E(a+n.a,max(b,a+n.b)); }
inline E &operator+=(const E &n) { return (*this)=(*this)+n,*this; }
inline bool cmp(const E &n)const
{
if(a<0&&n.a<0) return b<n.b;
if(a>=0&&n.a>=0) return a-b<n.a-n.b;
return a<0;
}
inline bool operator<(const E &n)const { return n.cmp(*this); }
inline int show()const { return cerr<<"("<<a<<", "<<b<<")\n",0; }
}val[N],vs[N];
struct MyHeap{
priority_queue<pair<E,int> > q;
map<pair<E,int>,int> d;
MyHeap() { while(!q.empty()) q.pop();d.clear(); }
inline int insert(pair<E,int> x) { return q.push(x),0; }
inline int del(pair<E,int> x) { return d[x]++; }
inline int top()
{
while(d[q.top()]) d[q.top()]--,q.pop();
return q.top().sec;
}
}hp;
namespace SEGMENT_space{
struct segment{
E val;segment *ch[2];
}*T[N];
inline int build(segment* &rt,int l,int r,int p,const E &v)
{
rt=new segment,rt->ch[0]=rt->ch[1]=NULL,rt->val=v;
int mid=(l+r)>>1;if(l==r) return 0;
if(p<=mid) build(rt->ch[0],l,mid,p,v);
else build(rt->ch[1],mid+1,r,p,v);return 0;
}
inline int push_up(segment* &rt)
{
rt->val=E(0,0);
if(rt->ch[0]!=NULL) rt->val+=rt->ch[0]->val;
if(rt->ch[1]!=NULL) rt->val+=rt->ch[1]->val;
return 0;
}
inline segment *_merge(segment* &x,segment* &y)
{
if(x==NULL) return y;if(y==NULL) return x;
x->ch[0]=_merge(x->ch[0],y->ch[0]);
x->ch[1]=_merge(x->ch[1],y->ch[1]);
return push_up(x),x;
}
}using SEGMENT_space::T;
using SEGMENT_space::build;
using SEGMENT_space::_merge;
inline int dfs(int x)
{
build(T[x],1,n,id[x],vs[x]);
Rep(i,g[x]) dfs(g[x][i]);
Rep(i,g[x]) T[x]=_merge(T[x],T[g[x][i]]);
return ans[x]=w[x]+T[x]->val.b,0;
}
int main()
{
inn(),n=inn(),uf.init(n);
rep(i,2,n) g[fa[i]=inn()].pb(i);
rep(i,1,n) w[i]=inn();
rep(x,1,n) Rep(i,g[x]) val[x].b+=w[g[x][i]];
rep(x,1,n) val[x].a=val[x].b-w[x],vs[x]=val[x];
rep(i,1,n) tl[i]=i,hp.insert(mp(val[i],i));int cnt=0;
rep(i,1,n)
{
int x=hp.top(),f=uf.findf(fa[x]);hp.del(mp(val[x],x));uf.merge(x,f);
if(!f) for(int y=x;y;y=R[y]) id[y]=++cnt;
else tl[f][R]=x,tl[f]=tl[x],hp.del(mp(val[f],f)),hp.insert(mp(val[f]+=val[x],f));
}
dfs(1);rep(i,1,n) printf("%lld ",ans[i]);return !printf("\n");
}