【题解】P2633 Count on a tree

P2633】题解

一:【题意】

  • 给定一棵树
  • m组询问
  • 求两点u,v间点权第K小

二:【解法】

  • 主席树
  • 对于每个节点u,建立u->root路径上的权值线段树tree[u]
  • 对于每次询问u,v
  • 树上差分得到tr=tree[u]+tree[v]-tree[lca(u,v)-tree[fa[lca(u,v)]]
  • 在tr上做线段树二分

三:【代码】

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10,Q=4*N+N*log2(N);
int nw[N];
vector<int> lsh;
vector<int> mp[N];
int tr[N];
struct node{
	int l,r;
	int son[2];
	int sum;
	#define l(q) tree[q].l
	#define r(q) tree[q].r
	#define sum(q) tree[q].sum
	#define ls(q) tree[q].son[0]
	#define rs(q) tree[q].son[1]
}tree[Q];int cnt;
void push_up(int q){
	sum(q)=sum(ls(q))+sum(rs(q));
}
void build(int &q,int l,int r){
	if(q==0) q=++cnt;
	l(q)=l;r(q)=r;
	if(l==r) return ;
	int mid=l+r>>1;
	build(ls(q),l,mid);
	build(rs(q),mid+1,r);
	push_up(q);
}
void update(int las,int &now,int tp,int d){
	if(now==0) now=++cnt;
	tree[now]=tree[las];
	
	int l=l(las),r=r(las);
	if(l==r){
		sum(now)=sum(las)+d;/////
		return ;
	}
	int mid=l+r>>1;
	int s=(tp>mid);
	update(tree[las].son[s],tree[now].son[s]=0,tp,d);
	push_up(now);
}
void Build(int u,int fa){
	update(tr[fa],tr[u],nw[u],1);
	for(auto v:mp[u]){
		if(v==fa) continue;
		Build(v,u);
	}
}
int query(int u,int v,int lca,int flca,int K){
	int l=l(u),r=r(u);
	if(l==r) return l;
	int res=sum(ls(u))+sum(ls(v))-sum(ls(lca))-sum(ls(flca));
	if(K<=res) return query(ls(u),ls(v),ls(lca),ls(flca),K);
	else return query(rs(u),rs(v),rs(lca),rs(flca),K-res);
}
int son[N],siz[N],dep[N];
int fa[N];
void Son(int u,int pa){
	fa[u]=pa;
	siz[u]=1;
	dep[u]=dep[pa]+1;
	for(auto v:mp[u]){
		if(v==pa) continue;
		Son(v,u);
		if(siz[v]>siz[son[u]]) son[u]=v;
	}
}
int top[N];
void Line(int u,int tp){
	top[u]=tp;
	if(!son[u]) return ;
	Line(son[u],tp);
	for(auto v:mp[u]){
		if(v==fa[u]||v==son[u]) continue;
		Line(v,v);
	}
}
int LCA(int a,int b){
	while(top[a]!=top[b]){
		if(dep[top[a]]<dep[top[b]]) swap(a,b);
		a=fa[top[a]];
	}
	if(dep[a]>dep[b]) swap(a,b);
	return a;
}
int main(){
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	int n,m;cin>>n>>m;
	lsh.push_back(-1);
	for(int i=1;i<=n;i++){
		cin>>nw[i];
		lsh.push_back(nw[i]);
	}
	sort(lsh.begin(),lsh.end());
	lsh.erase(unique(lsh.begin(),lsh.end()),lsh.end());
	for(int i=1;i<=n;i++) nw[i]=lower_bound(lsh.begin(),lsh.end(),nw[i])-lsh.begin();
	for(int i=1;i<n;i++){
		int a,b;cin>>a>>b;
		mp[a].push_back(b);
		mp[b].push_back(a);
	}
	build(tr[0],1,n);
	Build(1,0);
	Son(1,0);
	Line(1,1);
	int ans=0;
	while(m--){
		int u,v,K;cin>>u>>v>>K;
		u^=ans;
		int lca=LCA(u,v);
		ans=lsh[query(tr[u],tr[v],tr[lca],tr[fa[lca]],K)];
		cerr<<"-->";
		cout<<ans<<"\n";
	}
	return 0;
}
posted @ 2025-12-16 16:09  Ming3398  阅读(0)  评论(0)    收藏  举报