选点
选点
https://ac.nowcoder.com/acm/problem/22494
做法:dfs序+LIS
思路:
- 因为这是棵二叉树,所以可以使用结构体存储
- 由如果选了根节点的话,在这棵子树内选的其他的点都要比根节点的值大可以得出根节点<左节点,根节点<右节点
由如果在左子树选了一个点,在右子树中选的其他点要比它小可以得出右节点<左节点
所以根节点<右节点<左节点 根据递增关系可以进行根节点->右节点->左节点的访问顺序遍历 - 选出尽量多的点可以转化为遍历二叉树的顺序求最长上升子序列(LIS)的长度,这里采用贪心
的思想 不会的可以参考 最长不下降子序列 稍作修改即可
代码
#include <bits/stdc++.h> using namespace std; #define pb push_back #define mp(aa,bb) make_pair(aa,bb) #define _for(i,b) for(int i=(0);i<(b);i++) #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define per(i,b,a) for(int i=(b);i>=(a);i--) #define mst(abc,bca) memset(abc,bca,sizeof abc) #define X first #define Y second #define lowbit(a) (a&(-a)) typedef long long ll; typedef pair<int,int> pii; typedef unsigned long long ull; typedef long double ld; const int N=1e5+10; const int INF=0x3f3f3f3f; const int mod=998244353; const double eps=1e-6; const double PI=acos(-1.0); int n,dp[N]; struct node{ int l,r; ll w; }tree[N]; vector<ll> dfn; void dfs(int u){ if(!u) return; dfn.pb(tree[u].w); dfs(tree[u].r); dfs(tree[u].l); } void solve(){ cin>>n; rep(i,1,n) cin>>tree[i].w; rep(i,1,n){ cin>>tree[i].l>>tree[i].r; } dfs(1); fill(dp,dp+n,INF); // for(auto x:dfn){ // cout<<x<<" "; // } int m=dfn.size(); for(int i=0;i<m;i++){ *lower_bound(dp,dp+m,dfn[i])=dfn[i]; } cout<<lower_bound(dp,dp+m,INF)-dp<<"\n"; } int main(){ ios::sync_with_stdio(0); cin.tie(0); #ifdef DEBUG freopen("F:/laji/1.in", "r", stdin); // freopen("F:/laji/2.out", "w", stdout); #endif // int t;cin>>t;while(t--) solve(); return 0; }
牛客每日一题 文章被收录于专栏
水