牛客练习赛39 B.选点

链接:https://ac.nowcoder.com/acm/contest/368/B
来源:牛客网
 

题目描述

有一棵n个节点的二叉树,1为根节点,每个节点有一个值wi。现在要选出尽量多的点。

对于任意一棵子树,都要满足:

如果选了根节点的话,在这棵子树内选的其他的点都要比根节点的值

如果在左子树选了一个点,在右子树中选的其他点要比它

输入描述:

 

第一行一个整数n。

第二行n个整数wi,表示每个点的权值。

接下来n行,每行两个整数a,b。第i+2行表示第i个节点的左右儿子节点。没有为0。

n,a,b≤10^5,   −2×10^9≤wi≤2×10^9 

输出描述:

一行一个整数表示答案。

示例1

输入

复制

5
1 5 4 2 3
3 2
4 5
0 0
0 0
0 0 

输出

复制

3

思路:问题转换为求二叉树的前序遍历序列(先右后左)的一个最长上升子序列的长度。。。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f3f3f3f3f;
int n;ll w[100005];
int l[100005];int r[100005];
int ans=0;
ll b[100005];int cnt=0;
void dfs(int i)
{
    b[cnt++]=w[i];
    if(r[i]!=0)dfs(r[i]);
    if(l[i]!=0)dfs(l[i]);
}
int tmp[100005];
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%lld",&w[i]);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&l[i],&r[i]);
    }
    dfs(1);
    int len=0;
    for(int i=0;i<cnt;i++)
    {
        int id=lower_bound(tmp,tmp+len,b[i])-tmp;
        tmp[id]=b[i];
        len=max(len,id+1);
    }
    cout<<len<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/linruier2017/article/details/86777080