ARC110F Esoswap
由于 0 ∼ n − 1 0\sim n-1 0∼n−1 的特殊性,每次固定询问一个位置,询问 n n n 次一定会得到 0 0 0,且每次在这个位置上的数不会重复( 0 0 0 除外)。
于是考虑倒序将数固定,正序会出现问题。
然后把倒序排列转为正序排列。
具体地,先把 1 1 1 交换到位置 n − 1 n-1 n−1,然后将在 0 0 0 位置上的数与 1 1 1 交换,然后 1 1 1 一直往右移动到 n − 2 n-2 n−2,重复上面操作即可。
操作数 O ( n 2 ) \mathcal O(n ^2) O(n2)。
#include<cstdio>
//using namespace std;
typedef long long ll;
#define ha putchar(' ')
#define he putchar('\n')
inline int read() {
int x = 0;
char c = getchar();
while (c < '0' || c > '9')
c = getchar();
while (c >= '0' && c <= '9')
x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
return x;
}
inline void write(int x) {
if (x > 9)
write(x / 10);
putchar(x % 10 + 48);
}
void swap(int &a, int &b)
{
int t = a;
a = b, b = t;
}
const int _ = 107;
int n, a[_], id[_], as[200010];
void sol(int x) {
as[++as[0]] = x;
swap(id[a[x]], id[a[(x + a[x]) % n]]);
swap(a[x], a[(x + a[x]) % n]);
}
signed main() {
n = read();
for (int i = 0; i < n; ++i) a[i] = read(), id[a[i]] = i;
while (a[n - 1] != 0) sol(n - 1);
for (int i = n - 1; i >= 0; --i)
while (a[i] != n - 1 - i) sol(i);
sol(id[1]);
for(int i = n - 1; i > 1; --i)
{
sol(id[i]);
while(a[i - 1] != 1) sol(id[1]);
}
for (int i = 0; i <= as[0]; ++i) write(as[i]), he;
return 0;
}