牛客——选点(dfs序+LIS)
思路:
根据题意,选出来的子树应该满足:左子树的点的权值>右子树的点的权值>根节点的权值。
对树按照根右左的顺序求dfs序,在转化后的序列里求最长上升子序列即可。
代码:
///#pragma GCC optimize(3) ///#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline") ///#pragma GCC optimize(2) #include<bits/stdc++.h> using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<ll,ll>PLL; typedef pair<int,int>PII; typedef pair<double,double>PDD; #define I_int ll inline ll read() { ll x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-')f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); } return x*f; } char F[200]; inline void out(I_int x) { if (x == 0) return (void) (putchar('0')); I_int tmp = x > 0 ? x : -x; if (x < 0) putchar('-'); int cnt = 0; while (tmp > 0) { F[cnt++] = tmp % 10 + '0'; tmp /= 10; } while (cnt > 0) putchar(F[--cnt]); //cout<<" "; } ll ksm(ll a,ll b,ll p) { ll res=1; while(b) { if(b&1)res=res*a%p; a=a*a%p; b>>=1; } return res; } const int inf=0x3f3f3f3f,mod=998244353; const ll INF = 0x3f3f3f3f3f3f3f3f; const int maxn=1e5+100,maxm=3e5+7,N=1e6+7; const double PI = atan(1.0)*4; int w[maxn],n; int b[maxn],timetmp; PII e[maxn]; int q[maxn],cnt; int Find(int x){ int l=1,r=cnt; while(l<r){ int mid=(l+r)>>1; if(q[mid]>=x) r=mid; else l=mid+1; } return l; } void dfs(int u){ b[++timetmp]=w[u]; if(e[u].second) dfs(e[u].second);///注意顺序 if(e[u].first) dfs(e[u].first); } int main(){ ///输入 n=read(); for(int i=1;i<=n;i++) w[i]=read(); for(int i=1;i<=n;i++){ e[i].first=read(),e[i].second=read(); } ///求根右左的dfs序 dfs(1); ///nlogn求LIS q[++cnt]=b[1]; for(int i=2;i<=timetmp;i++) if(b[i]>q[cnt]) q[++cnt]=b[i]; else{ int tmp=Find(b[i]); q[tmp]=b[i]; } cout<<cnt<<endl; return 0; }