F 选点 前序遍历dfn序+dp求最长上升子序列 根<右子树<左子树选的点
链接:https://ac.nowcoder.com/acm/problem/22494
来源:牛客网
题目描述
有一棵n个节点的二叉树,1为根节点,每个节点有一个值wi。现在要选出尽量多的点。
对于任意一棵子树,都要满足:
如果选了根节点的话,在这棵子树内选的其他的点都要比根节点的值大;
如果在左子树选了一个点,在右子树中选的其他点要比它小。
输入描述:
第一行一个整数n。
第二行n个整数wi,表示每个点的权值。
接下来n行,每行两个整数a,b。第i+2行表示第i个节点的左右儿子节点。没有为0。
n,a,b≤105,−2×109≤wi≤2×109n,a,b\leq10^5, -2\times10^9\leq w_i \leq 2\times 10^9n,a,b≤105,−2×109≤wi≤2×109
输出描述:
一行一个整数表示答案。
分析:
按照根右左的顺序将所有值提取到一个数组里,
然后求这个数组的最长上升子序列就可以了
//-------------------------代码---------------------------- #define int ll const int N = 5e5+10; int n,m; struct node { ll l,r; } p[N]; ll a[N],dp[N],b[N],num = 0,len = 0; void dfs(ll x) { if(!x) return; b[++num] = a[x]; dfs(p[x].r); dfs(p[x].l); } void solve() { // cin>>n>>m; cin>>n; fo(i,1,n) { cin>>a[i]; } fo(i,1,n) { cin>>p[i].l>>p[i].r; } dfs(1); dp[++len] = b[1]; fo(i,2,num) { if(b[i] > dp[len]) dp[++len] = b[i]; else { auto t = upper_bound(dp+1, dp+1+len, b[i]) - dp; dp[t] = b[i]; } } // cout<<endl; cout<<len<<endl; } void main_init() {} signed main(){ AC();clapping();TLE; cout<<fixed<<setprecision(12); main_init(); // while(cin>>n,n) // while(cin>>n>>m,n,m) // int t;cin>>t;while(t -- ) solve(); // {solve(); } return 0; } /*样例区 */ //------------------------------------------------------------

浙公网安备 33010602011771号