NC22494 选点(思维+lis)
这题需要一点思维转化,感觉还是挺有意思的。
我们仔细观察选点的要求,发现,根要小于左右子树,左子树选的要大于右子树
因此,将他按根-右-左遍历之后,求一遍最长上升子序列就是答案
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pll; const int N=2e5+10; const int mod=1e9+7; int a[N],l[N],r[N]; int n,w[N],rt; int st[N],cnt; void dfs(int u){ int i; if(u==0) return ; a[++cnt]=w[u]; dfs(r[u]); dfs(l[u]); } vector<int> num; int main(){ ios::sync_with_stdio(false); int i; cin>>n; for(i=1;i<=n;i++) cin>>w[i]; for(i=1;i<=n;i++){ int a,b; cin>>a>>b; l[i]=a,r[i]=b; st[a]=st[b]=1; } for(i=1;i<=n;i++){ if(!st[i]){ rt=i; break; } } dfs(rt); num.push_back(a[1]); for(i=2;i<=n;i++){ if(a[i]>num.back()){ num.push_back(a[i]); } else{ int pos=lower_bound(num.begin(),num.end(),a[i])-num.begin(); num[pos]=a[i]; } } cout<<num.size()<<endl; return 0; }
没有人不辛苦,只有人不喊疼