CodeForces 1375E Inversion SwapSort
思路
考虑数列是一个排列怎么做。
套路地,设一个数组 \(b_i\) 表示 \(i\) 在排列出现的位置,即 \(a_{b_i} = i\)。则题中交换逆序对的位置就转化成了交换逆序对的值(因为若 \(i < j\) 且 \(b_i > b_j\) 则 \(a_{b_j} > a_{b_i}\))。直接一遍冒泡排序即可。
若数列不是一个排列,就强行将它转成排列。具体地,给所有数赋一个权值 \(p_i = \sum\limits_{j=1}^n [a_j < a_i] + \sum\limits_{j=1}^i [a_j = a_i]\),容易发现 \(p\) 是一个排列,且原数列里面的逆序对一定对应 \(p\) 中的一组逆序对。
因此这道题就做完了。时间复杂度 \(O(n^2)\)。
代码
code
/*
p_b_p_b txdy
AThousandSuns txdy
Wu_Ren txdy
Appleblue17 txdy
*/
#include <bits/stdc++.h>
#define pb push_back
#define fst first
#define scd second
#define mems(a, x) memset((a), (x), sizeof(a))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
typedef pair<int, int> pii;
const int maxn = 1010;
int n, b[maxn];
pii a[maxn];
bool cmp(pii a, pii b) {
return a.scd < b.scd;
}
void solve() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf("%d", &a[i].fst);
a[i].scd = i;
}
sort(a + 1, a + n + 1);
for (int i = 1; i <= n; ++i) {
a[i].fst = i;
}
sort(a + 1, a + n + 1, cmp);
for (int i = 1; i <= n; ++i) {
b[a[i].fst] = i;
}
vector<pii> ans;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n - i; ++j) {
if (b[j] > b[j + 1]) {
swap(b[j], b[j + 1]);
ans.pb(make_pair(b[j], b[j + 1]));
}
}
}
printf("%d\n", (int)ans.size());
for (pii p : ans) {
printf("%d %d\n", p.fst, p.scd);
}
}
int main() {
int T = 1;
// scanf("%d", &T);
while (T--) {
solve();
}
return 0;
}