CodeForces 1375E Inversion SwapSort

洛谷传送门

CF 传送门

思路

考虑数列是一个排列怎么做。

套路地,设一个数组 \(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;
}

posted @ 2022-07-21 14:26  zltzlt  阅读(76)  评论(0编辑  收藏  举报