[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\)
因果乃旋转纺车,光彩之多面明镜
浮世苍茫,不过瞬逝幻梦
善恶爱诳,皆有定数
于命运之轮中
吞噬于黄泉之冥暗
呜呼,吾乃梦之戍人
幻恋之观者
唯于万华镜中,永世长存
浮世苍茫,不过瞬逝幻梦
善恶爱诳,皆有定数
于命运之轮中
吞噬于黄泉之冥暗
呜呼,吾乃梦之戍人
幻恋之观者
唯于万华镜中,永世长存

浙公网安备 33010602011771号