题解 AtCoder Beginner Contest 367 E - Permute K times (*1370)
在博客园食用更佳:https://www.cnblogs.com/PinkRabbit/p/-/ABC367。
题意简述(*1370)
给定两个长度为
求经过以下变换
- 将
a 替换为b ,其中序列(b_1, \ldots, b_n) 定义为b_i = a_{x_i} 。
数据范围:
题解
注意到最后
- 一次后,第
i 位是原先的第x_i 位。 - 两次后,第
i 位是原先的第x_{x_i} 位。 - ……
把
可以看出,设从点
一张每个点恰好有一条出边的有向图是一片基环内向森林。至此本题被转化为基环内向森林上的“
可以通过倍增解决
时空复杂度为
注:由于这里的
参考 AC 代码
#include <iostream>
#include <vector>
using std::cin, std::cout;
#define F(i, a, b) for(int i = a; i <= (b); ++i)
void Solve();
int main() {
cin.sync_with_stdio(false);
cin.tie(nullptr);
Solve();
return 0;
}
using LL = long long;
void Solve() {
int n;
LL k;
cin >> n >> k;
std::vector<int> x[60], a(n + 1);
x[0].resize(n + 1);
F(i, 1, n)
cin >> x[0][i];
F(j, 0, 58) {
x[j + 1].resize(n + 1);
F(i, 1, n)
x[j + 1][i] = x[j][x[j][i]];
}
F(i, 1, n)
cin >> a[i];
F(i, 1, n) {
int p = i;
F(j, 0, 59)
if (k >> j & 1)
p = x[j][p];
cout << a[p] << " \n"[i == n];
}
}