题意
n个鸽子和笼子 编号1-n 每个鸽子在编号和自己一样的笼子里
三种操作
- 1 给定整数 a,b(1≤a≤N,1≤b≤N)将鸽子 a 从当前所在的巢中取出,放入巢 b。
- 2 给定整数 a,b(1≤a<b≤N)将巢 a 中所有鸽子移动到巢 b,同时将巢 b 中所有鸽子移动到巢 a。这两个移动操作是同时进行的。
- 3 给定整数 a(1≤a≤N) 输出鸽子 a 当前所在的巢的编号。
数据范围
- 1≤N≤1e6
- 1≤Q≤3e5
思路
数据范围很大 每次查询都要在o(1)完成
间接映射 有点巧妙 从洛谷的题解上学的
开三个数组 f[N],id[N],st[N]
维护一个数轴 数轴坐标id[a] 存储a号笼子对应的数轴坐标 通过笼子编号访问坐标 a为笼子编号
f[id[a]]存储数轴坐标上对应的笼子的编号
操作二时 交换a,b两个笼子 只需要交换id[a],id[b]上的笼子 之后再交换a,b对应的坐标
也就是
swap(f[id[a]],f[id[b]]);
swap(id[a],id[b]);
Code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define pii pair<int,int>
#define ar2 array<int,2>
#define ar3 array<int,3>
#define ar4 array<int,4>
#define endl '\n'
void cmax(int &a,int b){a=max(a,b);}
void cmin(int &a,int b){a=min(a,b);}
const int N=1e6+10,MOD=1e9+7,INF=0x3f3f3f3f,LINF=LLONG_MAX;
int id[N],f[N],st[N];
void solve() {
int n,q;cin>>n>>q;
for(int i=1;i<=n;i++){
id[i]=i,f[i]=i,st[i]=i;
}
while(q--){
int op,a,b;cin>>op;
if(op==3){
cin>>a;
cout<<f[st[a]]<<endl;
continue;
}
cin>>a>>b;
if(op==1){
st[a]=id[b];
}else if(op==2){
swap(f[id[a]],f[id[b]]);
swap(id[a],id[b]);
}
}
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int t=1;
// cin>>t;
while (t--) solve();
}