[树形dp]Hanging Hearts Codeforces1740E

Pak Chanek has 𝑛n blank heart-shaped cards. Card 11 is attached directly to the wall while each of the other cards is hanging onto exactly one other card by a piece of string. Specifically, card 𝑖i (𝑖>1i>1) is hanging onto card 𝑝𝑖pi (𝑝𝑖<𝑖pi<i).

In the very beginning, Pak Chanek must write one integer number on each card. He does this by choosing any permutation 𝑎a of [1,2,…,𝑛][1,2,…,n]. Then, the number written on card 𝑖i is 𝑎𝑖ai.

After that, Pak Chanek must do the following operation 𝑛n times while maintaining a sequence 𝑠s (which is initially empty):

  1. Choose a card 𝑥x such that no other cards are hanging onto it. 
  2. Append the number written on card 𝑥x to the end of 𝑠s. 
  3. If 𝑥≠1x≠1 and the number on card 𝑝𝑥px is larger than the number on card 𝑥x, replace the number on card 𝑝𝑥px with the number on card 𝑥x. 
  4. Remove card 𝑥x. 

After that, Pak Chanek will have a sequence 𝑠s with 𝑛n elements. What is the maximum length of the longest non-decreasing subsequence†† of 𝑠s at the end if Pak Chanek does all the steps optimally?

†† A sequence 𝑏b is a subsequence of a sequence 𝑐c if 𝑏b can be obtained from 𝑐c by deletion of several (possibly, zero or all) elements. For example, [3,1][3,1] is a subsequence of [3,2,1][3,2,1], [4,3,1][4,3,1] and [3,1][3,1], but not [1,3,3,7][1,3,3,7] and [3,10,4][3,10,4].

Input

The first line contains a single integer 𝑛n (2≤𝑛≤1052≤n≤105) — the number of heart-shaped cards.

The second line contains 𝑛−1n−1 integers 𝑝2,𝑝3,…,𝑝𝑛p2,p3,…,pn (1≤𝑝𝑖<𝑖1≤pi<i) describing which card that each card hangs onto.

Output

Print a single integer — the maximum length of the longest non-decreasing subsequence of 𝑠s at the end if Pak Chanek does all the steps optimally.

Examples

input

6
1 2 1 4 2

output

4

input

2
1

output

2

题意: 给出一棵树的结构,然后为树上每点分配点权,点权必须是一个排列,然后可以选择一个叶子结点,将其从树上删除并把它的权值放到串s中,如果该点点权小于父节点点权,则将其父节点点权修改为该点点权,问最终s串的非递降子序列最长长度。

分析: 设dp[i][0]表示不选i点时在其子树中能构成的最长子序列长度,dp[i][1]表示选i点时在其子树中能构成的最长子序列长度,可以发现,i点一定是其子树中最小的点,当选中i点后,要想非递减子序列最长,那么前面选的值必须和i点值相同,于是可以将那个最小值放在最长链的叶子结点上,这样整条链都是那个最小值了,所以dp[i][1] = i点的深度。而不选i点时,其子节点可选可不选,取一个最大值加起来就是dp[i][0]了,至于为什么可以加和,这是由于一开始构造的时候我们可以让不同子树对应不同的取值范围,这样就可以长度相加了。

具体代码如下:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cstring>
#include <cmath>
#include <vector> 
using namespace std;

vector<int> to[100005];
int dp[100005][2];//0表示不取i点,1表示取i点 

void dfs(int now, int fa){
	dp[now][0] = 0;
	dp[now][1] = 1;
	int mx = 0;
	for(int i = 0; i < to[now].size(); i++){
		int v = to[now][i];
		if(v == fa) continue;
		dfs(v, now);
		dp[now][0] += max(dp[v][0], dp[v][1]);
		mx = max(mx, dp[v][1]);
	}
	dp[now][1] += mx;	
}

signed main()
{
	int n;
	scanf("%d", &n);
	for(int i = 2; i <= n; i++){
		int fa;
		scanf("%d", &fa);
		to[fa].push_back(i);
		to[i].push_back(fa);
	} 
	dfs(1, 0);
	printf("%d\n", max(dp[1][0], dp[1][1]));
	
	return 0;
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值