法法塔是很喜欢写程序的。所以冒着就算码农屌丝一辈子的风险也大无畏地写着程序。
码农们为了表彰法法塔的坚持与执着,决定给法法塔颁布奖励,为了体现码农的屌丝气质,奖励也将由法法塔自己做出选择!
所有的奖励被组织成了一棵树的形态,每个点都有一个权值。法法塔首先选择一个子树,然后选择从该子树内的一个叶子节点到该子树的根的一条路径,将路径上节点的权值依次排成一个序列,求得这个序列的最长不下降子序列长度,这个长度就是他能得到的奖品数目。要求该子树的根必须被选择。
接下来就是法法塔进行选择的时间了。尽可能多地得到奖品是自然的。那么法法塔到底能够得到多少奖品呢?这是个很纠结的问题,他决定交给你来解决。对于每个子树,他都希望你能求出他首先选择了这个子树后,他能得到的最多的奖品数目。
第一行一个数n,描述树上节点的个数。
接下来一行n个数,描述树上每个点的父亲,点1为根,其父亲设为-1,其余每个点的父亲的标号都小于自己。
接下来一行n个数,表示树上每个点的权值。
一行n个数,第i个数表示法法塔选择了以第i个节点为根的子树后,他可以获得的最多的奖品个数。
输入1:
2
-1 1
1 1
输入2:
6
-1 1 2 1 2 4
4 3 4 3 6 2
输出1:
2 1
输出2:
3 1 1 2 1 1
n<=100000,每个数的权值都是1到n的正整数。
话说这题解法也很多啊。
100%
多种解法,分点答题。
cdq分治
由于这道题有三个限制,是一个三维偏序的问题。
三个限制分别是:(dfn是在进栈就加入,DFN是出栈加入)
dfn序里面x在y右边。
DFN序里面x在y左边。
value里,x小于等于y。
这样才能把x转移到y。
(其实就是二维偏序)
具体实现我不会。
树套树
我们发现,上面的dfn序是很有用的。
每次可以发现,第x的节点可以由dfn序中的一段的f得来。
而这一段就是表示x的子树。
其次,我们发现,x节点只能从value不比他大的节点转移而来.
有一个套路——我们设dfn序为坐标系中的y轴,value为x轴。
那么我们就可以利用树套树来进行维护。
我们套一个树状数组来维护x轴(因为是求1~value,所以可以利用树状数组)
然后再在树状数组中套线段树维护y轴即可。
当然,要动态开点(这个pascal选手量力而行,因为setlength贼慢,比赛我打直接T成傻子)
扫描线
这个其实我们利用树套树的套路,建立一个坐标系(矩阵)。
然后我们发现,每次选答案都是一个子矩阵的答案。
直接利用扫描线即可。
线段树合并
我们发现上面的方法都太神仙了。
我们回归简单的想法——
由于是求最长不下降子序列,一个原始做法就是建一颗权值线段树。
然鹅现在我们发现,在树上做这个东西的时候,我们可能会有很多的线段树要更新。
那么我们考虑线段树合并!
先把每个节点都建一颗线段树。
每次我们把一个点的儿子节点的线段树都合并起来,再更新当前节点的答案。
依次合并上去即可。
当然,setlength也是量力而行,我™用了就T78.
uses math;
type
new=record
l,r,ans:longint;
end;
var
i,j,k,l,n,m,tot,num,ans,gs:longint;
fa,val,id,en,ni,answer:array[1..100000] of longint;
son:array[1..100000] of boolean;
tov,next,last:array[1..200000] of longint;
tree:array[1..10000000] of new;
procedure insert(x,y:longint);
begin
inc(tot);
tov[tot]:=y;
next[tot]:=last[x];
last[x]:=tot;
end;
procedure mix(op,oq,l,r:longint);
var
m,xx,yy:longint;
begin
if (l=r) then
begin
tree[op].ans:=max(tree[op].ans,tree[oq].ans);
end
else
begin
m:=(l+r) shr 1;
xx:=tree[oq].l;yy:=tree[oq].r;
if tree[oq].l>0 then
begin
if tree[op].l=0 then tree[op].l:=tree[oq].l
else mix(tree[op].l,tree[oq].l,l,m);
end;
if tree[oq].r>0 then
begin
if tree[op].r=0 then tree[op].r:=tree[oq].r
else mix(tree[op].r,tree[oq].r,m+1,r);
end;
tree[op].ans:=max(tree[tree[op].l].ans,tree[tree[op].r].ans);
end;
end;
procedure change(x,l,r,val,gb:longint);
var
m:longint;
begin
if (l=r) then
begin
tree[x].ans:=gb;
end
else
begin
m:=(l+r)shr 1;
if val<=m then
begin
if tree[x].l=0 then
begin
inc(gs);
//setlength(tree,gs+1);
tree[x].l:=gs;
end;
change(tree[x].l,l,m,val,gb)
end
else
if val>m then
begin
if tree[x].r=0 then
begin
inc(gs);
//setlength(tree,gs+1);
tree[x].r:=gs;
end;
change(tree[x].r,m+1,r,val,gb);
end;
tree[x].ans:=0;
if tree[x].l>0 then tree[x].ans:=max(tree[x].ans,tree[tree[x].l].ans);
if tree[x].r>0 then tree[x].ans:=max(tree[x].ans,tree[tree[x].r].ans);
end;
end;
procedure get(x,l,r,st,en:longint);
var
m:longint;
begin
if (l=st)and(r=en) then
begin
ans:=max(ans,tree[x].ans)
end
else
begin
m:=(l+r)shr 1;
if (en<=m) and (tree[x].l>0) then get(tree[x].l,l,m,st,en)
else if (st>m) and (tree[x].r>0) then get(tree[x].r,m+1,r,st,en)
else
begin
if tree[x].l>0 then
get(tree[x].l,l,m,st,m);
if tree[x].r>0 then
get(tree[x].r,m+1,r,m+1,en);
end;
end;
end;
procedure dfs(x:longint);
var
i,j:longint;
bz:boolean;
begin
i:=last[x];
bz:=true;
while i>0 do
begin
if tov[i]<>fa[x] then
begin
bz:=false;
dfs(tov[i]);
mix(x,tov[i],1,n);
end;
i:=next[i];
end;
if bz then
begin
answer[x]:=1;
change(x,1,n,val[x],1);
end
else
begin
ans:=0;
get(x,1,n,1,val[x]);
answer[x]:=ans+1;
change(x,1,n,val[x],ans+1);
end;
end;
begin
//assign(input,'0data.in');reset(input);
//assign(output,'0data.out');rewrite(output);
readln(n);
for i:=1 to n do read(fa[i]);
fa[1]:=0;
for i:=2 to n do
begin
insert(i,fa[i]);insert(fa[i],i);
end;
for i:=1 to n do read(val[i]);
//setlength(tree,n+1);
gs:=n;
dfs(1);
for i:=1 to n do write(answer[i],' ');
writeln;
end.
end.