链接:https://ac.nowcoder.com/acm/contest/368/B
来源:牛客网
题目描述
有一棵n个节点的二叉树,1为根节点,每个节点有一个值wi。现在要选出尽量多的点。
对于任意一棵子树,都要满足:
如果选了根节点的话,在这棵子树内选的其他的点都要比根节点的值大;
如果在左子树选了一个点,在右子树中选的其他点要比它小。
输入描述:
第一行一个整数n。
第二行n个整数wi,表示每个点的权值。
接下来n行,每行两个整数a,b。第i+2行表示第i个节点的左右儿子节点。没有为0。
n,a,b≤105,−2×109≤wi≤2×109n,a,b≤105,−2×109≤wi≤2×109
输出描述:
一行一个整数表示答案。
示例1
输入
复制
5
1 5 4 2 3
3 2
4 5
0 0
0 0
0 0
输出
复制
3
题解是这样说的:
waht?神奇的理解和做法.题目稍微改一下就是另一种dfs序的LIS了,当时确实没想到
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int d[maxn],w[maxn],n;
vector<int>G[maxn],que;
void dfs(int root)
{
que.push_back(w[root]);
for(int i=0;i<G[root].size();i++)
dfs(G[root][i]);
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++) scanf("%d",&w[i]);
for(int i=1;i<=n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
if(v) G[i].push_back(v);
if(u) G[i].push_back(u);
}
dfs(1);
int id=0;
d[++id]=que[0];
for(int i=1;i<que.size();i++)
{
int v=que[i];
if(v>d[id]) d[++id]=v;
else
{
int j=lower_bound(d+1,d+1+id,v)-d;
d[j]=v;
}
}
cout<<id<<endl;
}