分享一下 单 l o g log log 做法 代码,本质上就是找离我左边最近的点和离我右边最近的点
#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
using namespace std;
using i64 = long long;
using i128 = __int128;
constexpr int maxn = 3e5+10,inf = 1e9;
int n,Q;
vector<int> g[maxn];
int fa[maxn][20],dep[maxn];//第二维取决于n的大小
int dfn[maxn],ff[maxn],idx,ans[maxn];
void dfs(int x,int f){
fa[x][0] = f;
dep[x] = dep[f]+1;
dfn[x]=++idx;
ff[idx]=x;
//cout<<x<<" "<<idx<<"\n";
for(auto y:g[x]){
if(y==f) continue;
dfs(y,x);
}
}
void Update(){
for(int j = 1;j<20;++j){
for(int i = 1;i<=n;++i){
fa[i][j] = fa[fa[i][j-1]][j-1];
}
}
}
int lca(int x,int y){
if(dep[x]<dep[y]) swap(x,y);
for(int i = 19;i>=0;--i){
if(dep[x]-dep[y]>=(1<<i)){
x = fa[x][i];
}
}
if(x==y) return x;
for(int i = 19;i>=0;--i){
if(fa[x][i]!=fa[y][i]){
x = fa[x][i],y = fa[y][i];
}
}
return fa[x][0];
}
struct segtree{
struct node{
i64 ma;
int nd;
}tree[maxn<<2];
int (*cmp)(i64 a,i64 b);
node ept;
void pushup(int k){
if(cmp(tree[k<<1].ma,tree[k<<1|1].ma))tree[k] = tree[k<<1];
else tree[k] = tree[k<<1|1];
}
void build(int k=1,int l=1,int r=n){
if(l==r){
tree[k] = ept;
return;
}
int mid=l+r>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
pushup(k);
}
void update(int x,i64 num,int k=1,int l=1,int r=n){
if(l==r){
tree[k].ma = num;
tree[k].nd = x;
return;
}
int mid=l+r>>1;
if(x<=mid)update(x,num,k<<1,l,mid);
else update(x,num,k<<1|1,mid+1,r);
pushup(k);
}
node query(int L,int R,int k=1,int l=1,int r=n){
if(r<L||R<l)return ept;
if(L<=l&&r<=R)return tree[k];
int mid=l+r>>1;
node a = query(L,R,k<<1,l,mid);
node b = query(L,R,k<<1|1,mid+1,r);
if(cmp(a.ma,b.ma))return a;
else return b;
}
}sma,smi;
int cmp1(i64 a,i64 b){return a>b;}
int cmp2(i64 a,i64 b){return a<b;}
int LCA(array<int,3> point){
int x = lca(point[0],point[1]);
int y = lca(point[0],point[2]);
int z = lca(point[1],point[2]);
if(dep[x]<dep[y]) swap(x,y);
if(dep[x]<dep[z]) swap(x,z);
return x;
}
void solve(){
cin>>n>>Q;
for(int i = 1;i<n;++i){
int x,y;
cin>>x>>y;
g[x].emplace_back(y);
g[y].emplace_back(x);
}
dfs(1,0);
Update();
vector<array<int,6>> q(Q,{{-1,-1,-1,-1,-1,-1}});
for(int i =0;i<Q;++i){
cin>>q[i][0]>>q[i][1]>>q[i][2];
q[i][3]=i;
}
sort(q.begin(),q.end(),[&](array<int,6> &x,array<int,6>&y){
return dfn[x[2]]<dfn[y[2]];
});
sma.cmp = cmp1;
sma.ept = {0,-1};
sma.build();
int id = 0;//dfn id
for(int i = 0;i<Q;++i){
while(id<dfn[q[i][2]]){
id++;
sma.update(ff[id],id);
}
q[i][5] = sma.query(q[i][0],q[i][1]).nd;
}
while(id<n){
id++;
sma.update(ff[id],id);
}
smi.cmp = cmp2;
smi.ept={inf,-1};
smi.build();
id = n+1;
for(int i= Q-1;i>=0;--i){
while(id>dfn[q[i][2]]){
id--;
smi.update(ff[id],id);
}
q[i][4]=smi.query(q[i][0],q[i][1]).nd;
}
while(id>1){
id--;
smi.update(ff[id],id);
}
for(int i = 0;i<Q;++i){
if(q[i][5]==-1) q[i][5] = sma.query(q[i][0],q[i][1]).nd;
if(q[i][4]==-1) q[i][4] = smi.query(q[i][0],q[i][1]).nd;
array<int,3> point={q[i][4],q[i][5],q[i][2]};
ans[q[i][3]] = LCA(point);
}
for(int i = 0;i<Q;++i) cout<<ans[i]<<"\n";
}
signed main(){
ios::sync_with_stdio(0);cin.tie(0);
solve();
return 0;
}