P11364 [NOIP2024] 树上查询
纪念这场把我创飞的 NOIP,为什么考场上写那么久还写不出来呢?
baka。
做过 P7880 应该很容易想到离线然后使用树上启发式合并预处理。设当前遍历到了点
如何找出所有的
然后处理询问,通过分讨交在左边,交在右边,以及包含的情况,不难发现限制是一个二维偏序,简单处理即可。
这样做时间复杂度是
不算并查集的话复杂度
upd:云斗上过了,应该没事。
#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <ctime>
#include <cstdio>
#include <random>
#include <vector>
#include <bitset>
#include <cassert>
#include <cstring>
#include <algorithm>
#define fi first
#define se second
#define MISAKA main
#define ll long long
#define eb emplace_back
#define pii pair<int,int>
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define _rep(i,a,b) for(int i=(a);i>=(b);--i)
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define FIO(FILE) freopen(FILE".in","r",stdin),freopen(FILE".out","w",stdout)
using namespace std;
bool __st;
inline int read(){
char ch=getchar();int f=1,x=0;
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*f;
}
const int N=5e5+10,mod=998244353;
int n,q,dfn[N],id[N],siz[N],tim,son[N],dep[N],ans[N],nxt[N],pre[N];
vector<int> g[N];set<int> s;
struct node{int x,y,k,id;
node(int a=0,int b=0,int c=0,int d=0){x=a,y=b,k=c,id=d;}
};vector<node> v1,v2;
bool cmp(node a,node b){return a.k>b.k;}
vector<pii> Q[N],v[N];
int gn(int x){return nxt[x]=x==nxt[x]?x:gn(nxt[x]);}
int gp(int x){return pre[x]=x==pre[x]?x:gp(pre[x]);}
void solve(int x,int L,int R,int d){
int p=gp(x),q=gn(x),flag=0;
while(L<=dfn[q+1]&&dfn[q+1]<=R) nxt[q]=q+1,pre[q+1]=q,q=gn(q+1),flag=1;
while(L<=dfn[p-1]&&dfn[p-1]<=R) pre[p]=p-1,nxt[p-1]=p,p=gp(p-1),flag=1;
if(flag) v1.eb(p,q,q-p+1,d),v[q].eb(p,d);
}
void dfs(int u,int f){
dep[u]=dep[f]+1,siz[u]=1;id[dfn[u]=++tim]=u;
for(int v:g[u])if(v!=f){
dfs(v,u),siz[u]+=siz[v];
if(siz[v]>siz[son[u]]) son[u]=v;
}
}
void dfs(int u,int f,int tp){
for(int v:g[u])if(v!=f&&v!=son[u]) dfs(v,u,0);
if(son[u]) dfs(son[u],u,1);
for(int v:g[u])if(v!=f&&v!=son[u])
rep(i,dfn[v],dfn[v]+siz[v]-1)
solve(id[i],dfn[u],dfn[u]+siz[u]-1,dep[u]);
solve(u,dfn[u],dfn[u]+siz[u]-1,dep[u]);
}
struct segtree{int l,r,mx;}t[N<<2];
void bd(int x,int l,int r){
t[x]={l,r,0};int mid=l+r>>1;
if(l^r) bd(2*x,l,mid),bd(2*x+1,mid+1,r);
}
void upd(int x,int p,int k){
t[x].mx=max(t[x].mx,k);
if(t[x].l^t[x].r) upd(2*x+(p>t[2*x].r),p,k);
}
int qry(int x,int l,int r){
if(t[x].r<l||t[x].l>r) return 0;
if(l<=t[x].l&&t[x].r<=r) return t[x].mx;
return max(qry(2*x,l,r),qry(2*x+1,l,r));
}
void misaka(){
n=read();
rep(i,2,n){
int u=read(),v=read();
g[u].eb(v);g[v].eb(u);
}
dfs(1,0);
rep(i,1,n) pre[i]=i,nxt[i]=i,v1.eb(i,i,1,dep[i]);
dfs(1,0,1);q=read();
rep(i,1,q){
int l=read(),r=read(),k=read();
Q[r].eb(l,i);v2.eb(l,r,k,i);
}
sort(v1.begin(),v1.end(),cmp);
sort(v2.begin(),v2.end(),cmp);
bd(1,1,n);
int j=0;rep(i,0,v2.size()-1){
while(j<v1.size()&&v1[j].k>=v2[i].k)
upd(1,v1[j].y,v1[j].id),j++;
int id=v2[i].id,l=v2[i].x+v2[i].k-1,r=v2[i].y;
ans[id]=max(ans[id],qry(1,l,r));
}
bd(1,1,n);
j=0;rep(i,0,v2.size()-1){
while(j<v1.size()&&v1[j].k>=v2[i].k)
upd(1,v1[j].x,v1[j].id),j++;
int id=v2[i].id,l=v2[i].x,r=v2[i].y-v2[i].k+1;
ans[id]=max(ans[id],qry(1,l,r));
}
bd(1,1,n);
_rep(i,n,1){
for(auto [x,y]:v[i]) upd(1,x,y);
for(auto [x,y]:Q[i]) ans[y]=max(ans[y],qry(1,1,x));
}
rep(i,1,q) printf("%d\n",ans[i]);
}
bool __ed;
signed MISAKA(){
#ifdef LOCAL_MSK
atexit([](){
debug("\n%.3lfs ",(double)clock()/CLOCKS_PER_SEC);
debug("%.3lfMB",abs(&__st-&__ed)/1024./1024);});
#endif
int T=1;
while(T--) misaka();
return 0;
}