链接:
https://ac.nowcoder.com/acm/contest/368/B
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld
题目描述
有一棵n个节点的二叉树,1为根节点,每个节点有一个值。现在要选出尽量多的点。
对于任意一棵子树,都要满足:
如果选了根节点的话,在这棵子树内选的其他的点都要比根节点的值大;
如果在左子树选了一个点,在右子树中选的其他点要比它小。
输入描述:
第一行一个整数n。第二行n个整数,表示每个点的权值。
接下来行,每行两个整数。第行表示第个节点的左右儿子节点。没有为。
输出描述:
一行一个整数表示答案。
输入
5
1 5 4 2 3
3 2
4 5
0 0
0 0
0 0
输出
3
Solve
题目要求选出来的点满足:左儿子权值>右儿子权值>父亲权值。对二叉树进行后续遍历,可以得到左儿子->右儿子->父亲
的排列,然后对遍历得到的结果反向求LIS即可
Code
#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define ms(a,b) memset(a,b,sizeof(a))
#define INF 0x7f7f7f7f
const int maxn=1e5+10;
const int mod=1e9+7;
using namespace std;
int w[maxn];
int arr[maxn];
int ar[maxn];
int dp[maxn];
struct wzy
{
int l,r;
}p[maxn];
int cnt;
void get_arr(int x)
{
if(p[x].l)
get_arr(p[x].l);
if(p[x].r)
get_arr(p[x].r);
arr[cnt++]=w[x];
}
int main(int argc, char const *argv[])
{
ios::sync_with_stdio(false);
cin.tie(0);
ms(p,0);
int n,a,b;
cin>>n;
for(int i=1;i<=n;i++)
cin>>w[i];
for(int i=1;i<=n;i++)
{
cin>>a>>b;
p[i].l=a;
p[i].r=b;
}
get_arr(1);
for(int i=0;i<cnt;i++)
ar[cnt-i-1]=arr[i];
int len=0;
for(int i=0;i<n;i++)
{
int pos=upper_bound(dp,dp+len,ar[i])-dp;
dp[pos]=ar[i];
len=max(len,pos+1);
}
cout<<len<<endl;
return 0;
}