LGP10241 [THUSC 2021] 白兰地厅的西瓜 学习笔记
LGP10241 [THUSC 2021] 白兰地厅的西瓜 学习笔记
题意简述
给定一棵 \(n\) 个结点的树,每个结点有一个点权 \(a_i\)。问树上最长的LIS的长度。
\(n\le 10^5\)。
做法解析
树上的任何一条简单路径显然可以被拆成最多两条直链。所以这题里面我们肯定是要把树DFS一遍,然后从下到上慢慢合并什么东西。
更新LIS包含路径最高点的答案比较显然,你用线段树合并的时候就是上升链顶比 \(a_u\) 小,下降链顶比 \(a_u\) 大的两条长度各自的最大值之和加个 \(1\)。
LIS不包含路径最高点的答案怎么办呢?你在线段树合并操作的过程中做。因为你的线段树是个值域线段树,所以一个结点两个儿子分别存的直链肯定是可以接上的。
代码实现
#include <bits/stdc++.h>
using namespace std;
using namespace obasic;
const int MaxN=2e5+5;
int N,A[MaxN],X,Y,ans,V=1e9+10;
vector<int> Tr[MaxN];
void addudge(int u,int v){
Tr[u].push_back(v);
Tr[v].push_back(u);
}
struct DynaSegTrees{
int ncnt,rt[MaxN],ls[MaxN<<5],rs[MaxN<<5];
struct node{
int f,g;node(){f=g=0;}node(int x,int y){f=x,g=y;}
friend node operator|(node &a,node &b){node c;c.f=max(a.f,b.f),c.g=max(a.g,b.g);return c;}
friend node& operator|=(node &a,node b){a=a|b;return a;}
}t[MaxN<<5];
void inse(int &u,int cl,int cr,int dd,int x,int typ){
if(!u)u=++ncnt;t[u]|={typ==1?x:0,typ==2?x:0};if(cl==cr)return;
int cmid=(cl+cr)>>1;dd<=cmid?inse(ls[u],cl,cmid,dd,x,typ):inse(rs[u],cmid+1,cr,dd,x,typ);
}
void merge(int &u1,int u2){
if(!u1){u1=u2;}if(!(u1^u2)||!u2)return;
maxxer(ans,t[ls[u1]].f+t[rs[u2]].g);
maxxer(ans,t[ls[u2]].f+t[rs[u1]].g);
t[u1]|=t[u2];merge(ls[u1],ls[u2]),merge(rs[u1],rs[u2]);
}
node query(int u,int cl,int cr,int dl,int dr){
if(dl<=cl&&cr<=dr)return t[u];
int cmid=(cl+cr)>>1;node res;
if(dl<=cmid)res|=query(ls[u],cl,cmid,dl,dr);
if(dr>cmid)res|=query(rs[u],cmid+1,cr,dl,dr);
return res;
}
}DTs;
int &trg(int i){return DTs.rt[i];}
void dfs(int u,int f){
int sl=0,sr=0;
for(auto v : Tr[u]){
if(v==f)continue;dfs(v,u);
int cl=DTs.query(trg(v),0,V,0,A[u]-1).f;
int cr=DTs.query(trg(v),0,V,A[u]+1,V).g;
maxxer(sl,cl),maxxer(sr,cr);
maxxer(ans,DTs.query(trg(u),0,V,A[u]+1,V).g+cl+1);
maxxer(ans,DTs.query(trg(u),0,V,0,A[u]-1).f+cr+1);
DTs.merge(trg(u),trg(v));
}
DTs.inse(trg(u),0,V,A[u],sr+1,2);
DTs.inse(trg(u),0,V,A[u],sl+1,1);
}
int main(){
readi(N);
for(int i=1;i<=N;i++)readi(A[i]);
for(int i=1;i<N;i++)readis(X,Y),addudge(X,Y);
dfs(1,0),writi(ans);
return 0;
}
反思总结
树上的LIS。好公式化啊。
浙公网安备 33010602011771号