[树形dp]选点

it2024-08-08  45

题目:选点

分析:

看似是树形dp,其实是个LIS 考虑到父节点跟左右儿子的大小关系,将三者按根、右儿子、左儿子排成一个数组,然后跑LIS即可,太妙了,我又没想出来。

代码:

#include <bits/stdc++.h> using namespace std; typedef long long ll;//三年竞赛一场空,不开long long见祖宗 //typedef __int128 lll; #define print(i) cout << "debug: " << i << endl #define close() ios::sync_with_stdio(0), cin.tie(0), cout.tie(0) #define mem(a, b) memset(a, b, sizeof(a)) #define pb(a) push_back(a) #define x first #define y second typedef pair<int, int> par; const ll mod = 1e9 + 7; const int maxn = 1e6 + 10; const int inf = 0x3f3f3f3f; int n; int l[maxn], r[maxn]; ll v[maxn], w[maxn]; int dp[maxn]; int len, tot; void dfs(int u) { if(!u) return; w[++tot] = v[u]; dfs(r[u]), dfs(l[u]); } int main() { cin >> n; for(int i = 1; i <= n; i++) cin >> v[i]; for(int i = 1; i <= n; i++) cin >> l[i] >> r[i]; dfs(1); for(int i = 1; i <= n; i++) { int id = upper_bound(dp + 1, dp + len + 1, w[i]) - dp; if(id == len + 1) dp[++len] = w[i]; else dp[id] = w[i]; } cout << len << endl; }
最新回复(0)