选点

选点

思路

本题思路及其有趣,我们一步步来思考。

我们先分析条件,本题需要我们在符合

如果选了根节点的话,在这棵子树内选的其他的点都要比根节点的值

如果在左子树选了一个点,在右子树中选的其他点要比它

也就是说,我们所有选的点的权值,需要满足

左>右>根

在该条件下,能选择尽量多的点。

这里我们直接揭秘,太巧秒了。

我们可以以根,右,左的顺序来建立dfs序

这样我们所求的满足条件的最多的点,就是在dfs序下的LIS了。

总结

我们看到,类似的左右根需要满足按照一定的性质排序。则可以将性质从树上操作转变为区间操作。

Ac_code

#include<bits/stdc++.h>
using namespace std;
#define ios ios::sync_with_stdio(false); cin.tie(0), cout.tie(0)
const int N = 1e5 + 10;
int n,root;
bool st[N];
int l[N],r[N],w[N],q[N];
int dfn[N],ts;

void dfs(int u)
{
    dfn[++ts] = u;
    if(r[u]) dfs(r[u]);
    if(l[u]) dfs(l[u]);
}

int main()
{
    ios;
    cin>>n;
    for(int i=1;i<=n;i++) cin>>w[i];
    for(int i=1;i<=n;i++) cin>>l[i]>>r[i],st[l[i]] = st[r[i]] = 1;
    for(int i=1;i<=n;i++) 
        if(!st[i]) 
        {
            root = i;
            break;
        }
    dfs(root);
    int len = 0;
    for(int i=1;i<=n;i++)
    {
        int l = 0,r = len;
        while(l<r)
        {
            int mid = l + r + 1 >> 1;
            if(q[mid]<w[dfn[i]]) l = mid;
            else r = mid - 1;
        }
        len = max(len,r+1);
        q[r+1] = w[dfn[i]];
    }
    cout<<len<<"\n";
    return 0;
}
posted @ 2022-06-30 17:03  艾特玖  阅读(74)  评论(0)    收藏  举报