[CF1375E] Inversion SwapSort

[CF1375E] Inversion SwapSort - 构造

Description

给定一个长度为 (n) 的序列 (a),求 (a) 中的所有逆序对 ((i_1, j_1), (i_2, j_2), cdots, (i_m, j_m)) 的一个排列 (p),使得依次交换 ((a_{i_{p_1}}, a_{j_{p_1}}), (a_{i_{p_2}}, a_{j_{p_2}}), cdots, (a_{i_{p_m}}, a_{j_{p_m}})) 后序列单调不降。(1 le n le 10^3)(1 le a_i le 10^9)

Solution

什么样的过程才能让所有逆序对(绑定位置!)恰好交换一次呢?

先问:什么样的过程才能让所有逆序对(绑定元素本身!)恰好交换一次呢?

冒泡排序

我们对序列做冒泡排序,每次记录被交换元素的下标即可

回到原问题

我们求出一个排列,表示最终每个位置要放现在哪个位置的元素

然后按上面的做法对这个排列做即可

为了方便理解这个过程,可以画一个二部图,左 b[i] 和右 i 连接

#include <bits/stdc++.h>
using namespace std;

#define int long long

signed main()
{
    ios::sync_with_stdio(false);

    int n;
    cin >> n;
    vector<pair<int, int>> a(n + 2);

    for (int i = 1; i <= n; i++)
        cin >> a[i].first, a[i].second = i;

    sort(&a[1], &a[n + 1]);

    vector<int> b(n + 2);
    for (int i = 1; i <= n; i++)
        b[i] = a[i].second;

    vector<pair<int, int>> ans;

    for (int i = 1; i <= n; i++)
        for (int j = 1; j < n; j++)
            if (b[j] > b[j + 1])
            {
                ans.push_back({b[j + 1], b[j]});
                swap(b[j], b[j + 1]);
            }

    cout << ans.size() << endl;
    for (auto [x, y] : ans)
        cout << x << " " << y << endl;
}
原文地址:https://www.cnblogs.com/mollnn/p/14473424.html