列表

详情


NC22494. 选点

描述

有一棵n个节点的二叉树,1为根节点,每个节点有一个值wi。现在要选出尽量多的点。
对于任意一棵子树,都要满足:
如果选了根节点的话,在这棵子树内选的其他的点都要比根节点的值
如果在左子树选了一个点,在右子树中选的其他点要比它

输入描述

第一行一个整数n。

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

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

输出描述

一行一个整数表示答案。

示例1

输入:

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

输出:

3

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 58ms, 内存消耗: 5212K, 提交时间: 2019-02-09 16:55:28

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int l[maxn],r[maxn],f[maxn],q[maxn],tot,w[maxn];
void dfs(int p){
	if(p==0)
		return ;
	q[++tot]=p;
	dfs(r[p]);
	dfs(l[p]);
}
int main(){
	int n,ans=1;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%d",&w[i]);
	for(int i=1;i<=n;i++)
		scanf("%d%d",&l[i],&r[i]);
	dfs(1);
	for(int i=1;i<=n;i++)
		q[i]=w[q[i]];
	f[1]=q[1];
	for(int i=2;i<=n;i++){
		if(q[i]>f[ans])
			f[++ans]=q[i];
		else{
			int pos=lower_bound(f+1,f+1+ans,q[i])-f;
			f[pos]=q[i];
		}
	}
	printf("%d\n",ans);
} 

C++11(clang++ 3.9) 解法, 执行用时: 54ms, 内存消耗: 3960K, 提交时间: 2019-02-08 21:55:33

#include<bits/stdc++.h>
using namespace std;const int N=1e5+7,inf=2e9+7;
int ls[N],rs[N],w[N],n,m,i,j,a[N],b[N],ind,tot,pos;
void dfs(int x){if(!x)return;a[++ind]=w[x];dfs(rs[x]);dfs(ls[x]);}
int main(){
	for(scanf("%d",&n),i=1;i<=n;++i)scanf("%d",w+i);
	for(i=1;i<=n;++i)scanf("%d%d",ls+i,rs+i);
	for(dfs(1),i=0;i<=n;++i)b[i]=inf;
	for(i=1;i<=n;++i){
		pos=lower_bound(b,b+tot,a[i])-b;
		b[pos]=min(b[pos],a[i]);
		tot=max(pos+1,tot);
	}printf("%d\n",tot);
}

上一题