[題解]AT_abc279_f [ABC279F] BOX

WaterSunHB發表於2024-06-23

思路

對於操作 1,我們可以看做將 \(x\) 號集合與 \(y\) 號集合合併,並將原本的 \(y\) 號集合重新開一個並查集維護。

對於操作 2,我們可以開一個陣列維護每一個球所在哪一個並查集中。

對於操作 3,在操作 1 中維護每一個並查集對於了哪一個箱子即可。

因為 \(n + q \leq 6 \times 10^5\),所以陣列開 \(6 \times 10^5\) 即可。

Code

#include <bits/stdc++.h>  
#define re register  
  
using namespace std;  
  
const int N = 6e5 + 10;  
int n,q,idx,num;  
int f[N],bd[N],nd[N],box[N];  
/*  
f 維護並查集  
bd 維護每一個箱子對應的並查集  
nd 維護每一個球對應的並查集  
box 維護每一個並查集對於的箱子   
*/   
  
inline int read(){  
    int r = 0,w = 1;  
    char c = getchar();  
    while (c < '0' || c > '9'){  
        if (c == '-') w = -1;  
        c = getchar();  
    }  
    while (c >= '0' && c <= '9'){  
        r = (r << 1) + (r << 3) + (c ^ 48);  
        c = getchar();  
    }  
    return r * w;  
}  
  
inline int find(int x){  
    if (f[x] != x) return f[x] = find(f[x]);  
    return f[x];  
}  
  
int main(){  
    n = idx = num = read();  
    q = read();  
    for (re int i = 1;i <= n;i++) f[i] = bd[i] = nd[i] = box[i] = i;  
    while (q--){  
        int op;  
        op = read();  
        if (op == 1){  
            int x,y;  
            x = read();  
            y = read();  
            f[bd[y]] = find(bd[x]);  
            bd[y] = ++idx;  
            f[idx] = idx;  
            box[idx] = y;  
        }  
        else if (op == 2){  
            int x;  
            x = read();  
            nd[++num] = bd[x];  
        }  
        else{  
            int x;  
            x = read();  
            printf("%d\n",box[find(nd[x])]);  
        }  
    }  
    return 0;  
}  

相關文章