[ABC295G] Minimum Reachable City

[ABC295G] Minimum Reachable City

Description

给定一张点数为 \(N\) 的有向图,初始 \(p_i(1\leq p_i \leq i,1 \leq i < N)\) 连向 \(i+1\)

\(Q\) 次操作,有两种:

- 1 u v\(u\)\(v\) 连一条有向边,保证最开始时 \(v\) 能到达 \(u\)\(u \ne v\)

- 2 x:询问 \(x\) 能到达的点中编号最小的点。

Solutions

  • 操作一可以看作 \(u \to v\) 路径上所有点向 \(v\) 连边,我们可以优化为每个点向父节点连边。

  • 操作二相当于从 \(x\) 出发,沿我们添加的边向上走到最高点。

    我们考虑使用并查集实现,操作一暴力跳就可以。

Code

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+7;
int n,q,op,u,v;
int p[N],f[N];
int find(int x){return x==f[x]?x:f[x]=find(f[x]);}
void merge(int x,int y){
	x=find(x);y=find(y);
	if(x==y) return;
	f[y]=x;
}
int main(){
	scanf("%d",&n);
	for(int i=2;i<=n;++i) scanf("%d",&p[i]);
	for(int i=1;i<=n;++i) f[i]=i;
	scanf("%d",&q);
	while(q--){
		scanf("%d",&op);
		if(op==1){
			scanf("%d%d",&u,&v);
			u=find(u);
			while(u>v){
				merge(p[u],u);u=find(u);
			}
		}
		else scanf("%d",&u),printf("%d\n",find(u));
	}
	return 0;
}
posted @ 2023-07-25 14:15  Zimo_666  阅读(5)  评论(0编辑  收藏  举报