CF893F

CF893F

首先,我们发现,这个题只需要子树内的答案,且只需要维护最小值。

注意到对于两个点 i,j,若 depi>depj,且 valivalj,则对于 lca(i,j) 及其它的父亲,i 都是一个无用的点。

注意到 n105,m106,这启发我们进行预处理以做到 O(logn) 单次询问。

考虑进行广搜,设当前在搜 dep=k 的点,动态维护 u 的子树中距离与它不超过 kdepu 的节点的最小值 wu

我们暴力地从当前点 u 往上跳父亲,若遇到第一个 x 满足 wxvalu,则对于 x 以及其祖先,u 都是一个无用的点,直接 break

在没有遇到之前,我们边跳边用一颗动态开点线段树维护答案,也即第 x 棵线段树的第 i 个位置是有效的距离为 i 的点的权值。这里满足这个权值单调递减。然后令 wx=valu

然后我们暴力查区间最小值即可。

void init(){
	queue<int>q;
	q.push(r);
	while(!q.empty()){
		int u=q.front();q.pop();
		dep[u]=dep[fa[u]]+1;
		int dis=1,v=fa[u];
		insert(rt[u],1,n,dis,val[u]);	
		while(val[v]>val[u]){
			++dis;insert(rt[v],1,n,dis,val[u]);val[v]=val[u];
			v=fa[v];
		}
		for(auto v:g[u]){
			if(v==fa[u])continue;
			q.push(v);
		}
	}
}
int ask(int u,int k){
	return find(rt[u],1,n,1,k); 
}
signed main(){
	ios::sync_with_stdio(false);
	cin>>n>>r;val[0]=-0x3f3f3f3f;
	for(int i=1;i<=n;i++)cin>>val[i];
	for(int i=1;i<n;i++){
		int u,v;cin>>u>>v;
		g[u].push_back(v);g[v].push_back(u);
	}
	for(int i=1;i<=n;i++){
		random_shuffle(g[i].begin(),g[i].end());
	} 
	dfs(r,0);
	init();
	cin>>m;int lst=0;
	while(m--){
		int u,k;cin>>u>>k;
		u=(u+lst)%n+1;k=(k+lst)%n;++k;
		lst=ask(u,k);cout<<lst<<"\n";
	}
}

code

posted @   spdarkle  阅读(16)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示