0%

Codeforces 1602B Special Permutation

第一次写题解,大佬轻喷。

题目大意

给定数组 \(a\) ,每次变换将 \(a_i\) 变换为 \(a\)\(a_i\) 出现的次数。询问 \(k\) 次变换后 \(a_x\) 的值。

\(e.g.\) \[ \begin{array}{cc} \text{初始数组} &2 \ 1 \ 1 \ 4 \ 3 \ 1 \ 2 \\ \text{第一次变换后} & 2 \ 3 \ 3 \ 1 \ 1 \ 3 \ 2 \\ \text{第二次变换后} & 2 \ 3 \ 3 \ 2 \ 2 \ 3 \ 2 \\ \text{第三次变换后} & 4 \ 3 \ 3 \ 4 \ 4 \ 3 \ 4 \\ \dots &\dots \\ \end{array} \]

分析

我们称 \(a\) 中所有相同的元素为一

容易发现,当一组内的元素等于其出现次数时,这组元素便不再变化。我们称这种状态为稳定

所以说,当没有组发生合并,也就是所有元素都不发生变化时,以后也不会再有变化。此时整个数组稳定

换言之,在整个数组稳定前,组的数量严格递减

很容易得出最多变换 \(n\) 次整个数组便稳定的结论。

(官方题解说最多 \(\log n\) 次就会达到稳定,可是我不会证。不过 \(n\) 次的复杂度也足够通过此题了。)

代码

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
#include <cstdio>
#include <iostream>

const int MAX_N = 2050;

int a[MAX_N][MAX_N];

template <typename T>
T read();

int main() {
std::ios::sync_with_stdio(false);

int T = read<int>();
while (T--) {
int n = read<int>();

for (int i = 1; i <= n; i++) {
a[0][i] = read<int>();
}
for (int i = 1; i <= n; i++) {
auto *cnt = new int[n + 1]{};
for (int j = 1; j <= n; j++) {
cnt[a[i - 1][j]]++;
}
for (int j = 1; j <= n; j++) {
a[i][j] = cnt[a[i - 1][j]];
}
}

int q = read<int>();
while (q--) {
int x = read<int>(), y = read<int>();
std::cout << a[std::min(y, n)][x] << '\n';
}
}

return 0;
}