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;
}
View Code

 

posted @ 2021-04-02 21:55  朝暮不思  阅读(46)  评论(0编辑  收藏  举报