【分块优化】H. Permutation and Queries
给定一个序列ne。
ne[i]
代表着若当前位置为i的下一个跳转的位置为ne[i]
,比如ne[3]=5
代表着说当前位置为3的下一个要跳转到的位置为5.
并进行q次操作,操作类型分为两种。
- 一种是
swap(ne[i],ne[j])
- 另外一种是
move(x,k)
,需要输出将x=ne[x]进行k次迭代后的结果。
思路:
使用分块维护x在跳转\(int(\sqrt q)\)后的结果。
在使用swap操作后要进行更新维护。
(类似对两个链表交换中间某两个结点的操作)
#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define MAX 1000005
#define MOD 1000000007
using namespace std;
const int N = 3E5+5,M = 6E5+10;
int n,m,q,ne[N],pre[N],jmp[N],len,opt,x,y;
inline int move(int x,int k)
{
repd(i,1,k) x = ne[x];
return x;
}
inline void modi(int st)
{
int fin = st;
repd(i,1,len-1) st = pre[st];
fin = ne[fin];
repd(i,1,len)
{
jmp[st] = fin;
st = ne[st];
fin = ne[fin];
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>q;
len = int(sqrt(n));
repd(i,1,n) cin>>ne[i];
repd(i,1,n) pre[ne[i]] = i;
repd(i,1,n) jmp[i] = move(i,len);
repd(i,1,q)
{
cin>>opt>>x>>y;
if(opt==1)
{
swap(pre[ne[x]],pre[ne[y]]);
swap(ne[x],ne[y]);
modi(x);modi(y);
}
else if(opt==2)
{
while(y-len>=0) x = jmp[x],y -= len;
cout<<move(x,y)<<endl;
}
}
return 0;
}