K. 翻转排序

知识点:选择排序、排列的性质

重要发现:可以通过翻转 之后再翻转 来交换 , 两个元素的位置,而不影响其他位置。

维护每个位置的元素、以及每个元素在什么位置这两个数组,每次把元素 换到第 个位置上,同时更新这两个数组中的信息。

如果没发现这个性质,也可以使用 Splay 等数据结构维护每个元素的位置,这样只用 次翻转操作就可以了。当然,这种做法有点超纲了,并不推荐这样做。

标程

C++

#include <bits/stdc++.h>

using namespace std;

constexpr int N = 200000 + 9;

int n;
int a[N], pos[N];

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    cin >> n;
    for (int i = 1; i <= n; ++i)
    {
        cin >> a[i];
        pos[a[i]] = i;
    }

    vector<pair<int, int>> ans;
    for (int i = 1; i <= n; ++i)
    {
        int l = i, r = pos[i];
        swap(pos[a[i]], pos[i]);
        swap(a[l], a[r]);
        ans.push_back({l, r});
        if (r - l >= 2) // 区间长度大于等于 3
            ans.push_back({l + 1, r - 1});
    }

    cout << ans.size() << '\n';
    for (auto [l, r] : ans)
        cout << l << ' ' << r << '\n';
}

Java

import java.util.*;
import java.io.*;

public class Main {
    static Kattio io = new Kattio();

    public static void main(String[] args) {
        int n = io.nextInt();
        int a[] = new int[n + 1];
        int pos[] = new int[n + 1];
        for (int i = 1; i <= n; i++) {
            a[i] = io.nextInt();
            pos[a[i]] = i;
        }
        Vector<int[]> ans = new Vector<>();
        for (int i = 1; i <= n; i++) {
            int l = i, r = pos[i];

            int tmp = pos[a[i]];
            pos[a[i]] = pos[i];
            pos[i] = tmp;

            tmp = a[l];
            a[l] = a[r];
            a[r] = tmp;

            ans.add(new int[]{l, r});
            if (r - l >= 2) {
                ans.add(new int[]{l + 1, r - 1});
            }
        }
        io.println(ans.size());
        for (int[] p : ans) {
            io.println(p[0] + " " + p[1]);
        }

        io.close();
    }
}

class Kattio extends PrintWriter {
    private BufferedReader r;
    private StringTokenizer st;
    // 标准 IO
    public Kattio() { this(System.in, System.out); }
    public Kattio(InputStream i, OutputStream o) {
        super(o);
        r = new BufferedReader(new InputStreamReader(i));
    }
    // 在没有其他输入时返回 null
    public String next() {
        try {
            while (st == null || !st.hasMoreTokens())
                st = new StringTokenizer(r.readLine());
            return st.nextToken();
        } catch (Exception e) {}
        return null;
    }
    public int nextInt() { return Integer.parseInt(next()); }
    public double nextDouble() { return Double.parseDouble(next()); }
    public long nextLong() { return Long.parseLong(next()); }
}

Python

n = int(input())
a = [0] + list(map(int, input().split()))
pos = [0] * (n + 1)
for i in range(1, n + 1):
    pos[a[i]] = i
ans = []
for i in range(1, n + 1):
    l, r = i, pos[i]
    pos[a[i]], pos[i] = pos[i], pos[a[i]]
    a[l], a[r] = a[r], a[l]
    ans.append((l, r))
    if r - l >= 2:
        ans.append((l + 1, r - 1))
print(len(ans))
for l, r in ans:
    print(l, r)