ABC295G 题解

  • 1253 字
  1. 1. 题意简述
  2. 2. 分析
  3. 3. 代码
  4. 4. 闲话

“「あるべき人間の姿へ」 「正しい人間の姿へ」 そう思えばなんだか 人間全てが汚く思えてくるな”—— 《不可解》

题意简述

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

QQ 次操作,有两种:

  • 1 u vuuvv 连一条有向边,保证最开始时 vv 能到达 uuuvu \ne v
  • 2 x:询问 xx 能到达的点中编号最小的点。

分析

最开始时,uu 能到达的所有点都比 uu 大。而操作 11 形成了一个强联通分量,走强联通分量内部的点才可能达到更小的点。

一个点 xx 能达到的最小的点在 xx 所在的强连通分量里,用并查集维护即可。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
const int N = 200005;
int fa[N],p[N];
int n;

int find(int x){
if(fa[x]==x)
return fa[x];
return fa[x]=find(fa[x]);
}

int main(){
cin >> n;
for(int k=2;k<=n;k++)
cin >> p[k];
for(int k=1;k<=n;k++)
fa[k] = k;
int q;
cin >> q;
while(q--){
int t;
cin >> t;
if(t==1){
int u,v;
cin >> u >> v;
v = find(v);
while(find(u)!=v){
fa[find(u)] = find(p[u]);
u = p[u];
}
fa[find(u)] = v;
}
else{
int x;
cin >> x;
cout << find(x) << endl;
}
}
return 0;
}

闲话

警惕 abc 打普及 G 牌。