选点
思路
本题思路及其有趣,我们一步步来思考。
我们先分析条件,本题需要我们在符合
如果选了根节点的话,在这棵子树内选的其他的点都要比根节点的值大;
如果在左子树选了一个点,在右子树中选的其他点要比它小。
也就是说,我们所有选的点的权值,需要满足
左>右>根
在该条件下,能选择尽量多的点。
这里我们直接揭秘,太巧秒了。
我们可以以根,右,左的顺序来建立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;
}

浙公网安备 33010602011771号