[FJOI2021模拟] tree

[FJOI2021模拟] tree

题意:树上最长严格上升子序列

不难想到枚举\(lca\),计算子树内的\(\text{LIS,LDS}\)\(n^2\log_2n\)的暴力

由于\(f_{u,x}\)表示长度为\(x\)\(u\)\(\tt LIS,LDS\)的结尾最大/小值。

由于不会超过子树高度,考虑长链剖分

时间复杂度\(O(n\log_2 n)\)

\(\mathfrak{Talk\ is\ cheat,show\ you\ the\ shit.}\)

#include<bits/stdc++.h>
using namespace std;
# define fre(k) freopen(k".in","r",stdin);freopen(k".out","w",stdout)
# define ll long long
# define read read1<ll>()
# define Type template<typename T>
Type T read1(){
	T t=0;
	char k;
	bool vis=0;
	do (k=getchar())=='-'&&(vis=1);while('0'>k||k>'9');
	while('0'<=k&&k<='9')t=(t<<3)+(t<<1)+(k^'0'),k=getchar();
	return vis?-t:t;
}
vector<int>G[100005];
int s,a[100005],h[100005],son[100005],ans,hx[300005],NOW;
void dfs(int n,int fa){
	for(int i=0;i<G[n].size();++i)
		if(G[n][i]!=fa){
			dfs(G[n][i],n);
			if(h[son[n]]<=h[G[n][i]])son[n]=G[n][i];
		}h[n]=h[son[n]]+1;
}
int cmp(int x,int y){return x>y;}
int* New(int n){
	int* w=hx+NOW;NOW+=n;
	return w;
}
void dfs(int n,int fa,int* Up,int* Down){
	if(son[n])dfs(son[n],n,Up,Down);
	int w=lower_bound(Up,Up+h[n]+1,a[n])-Up;
	ans=max(ans,w);Up[w]=a[n];
	w=lower_bound(Down,Down+h[n]+1,a[n],cmp)-Down;
	ans=max(ans,w);Down[w]=a[n];
	for(int i=0;i<G[n].size();++i)
		if(G[n][i]!=son[n]&&G[n][i]!=fa){
			int u=G[n][i],*x=New(h[u]+1),*y=New(h[u]+1);
			memset(x,0x7f,h[u]+1<<2);x[0]=-x[0];
			memset(y,-0x7f,h[u]+1<<2);y[0]=-y[0];
			dfs(u,n,x,y);
			for(int j=1;j<=h[u];++j){
				if(y[j]>-2e9){
					w=lower_bound(Up,Up+h[n]+1,y[j])-Up-1;
					ans=max(ans,w+j);
				}
				if(x[j]<2e9){
					w=lower_bound(Down,Down+h[n]+1,x[j],cmp)-Down-1;
					ans=max(ans,w+j);
				}
			}
			for(int j=0;j<=h[u];++j){
				Up[j]=min(Up[j],x[j]);
				Down[j]=max(Down[j],y[j]);
			}
			w=lower_bound(Up,Up+h[n]+1,a[n])-Up;
			ans=max(ans,w);Up[w]=a[n];
			w=lower_bound(Down,Down+h[n]+1,a[n],cmp)-Down;
			ans=max(ans,w);Down[w]=a[n];
		}
}
int main(){
//	fre("tree");
	s=read;
	for(int i=1;i<=s;++i)a[i]=read;
	for(int i=1;i<s;++i){
		int u=read,v=read;
		G[u].push_back(v);
		G[v].push_back(u);
	}dfs(1,0);
	int *x=New(h[1]+1),*y=New(h[1]+1);
	memset(x,0x7f,h[1]+1<<2);x[0]=-x[0];
	memset(y,-0x7f,h[1]+1<<2);y[0]=-y[0];
	dfs(1,0,x,y);
	cout<<ans<<endl;
	return 0;
}	

考场上打爆了 😃,得了\(20pt\)

posted @ 2021-03-18 16:39  ファイナル  阅读(49)  评论(0)    收藏  举报