CF1375E Solution

题目链接

题解

将所有逆序对((x_i,y_i))按照(y_i)降序排序,若(y_i)相等则按(a_{x_i})((a)​为原序列)升序排序,若两者均相等则按(x_i)升序排序即可。

对于序列(a),如果每次寻找一组逆序对并将它们交换,易得经过若干组操作后一定可以化为单调不降的序列,因此我们只需保证在交换原有逆序对过程中不产生新逆序对即可。考虑从后往前依次归位((y_i)降序),易得按(a_{x_i})升序排序的话,原先最小的(a_{x_i})到了次小的(a_{x_i})位置上,次小的则到了第三小的位置上,以此类推,而最大的到达了(y_i)上,(a_{y_i})到达了最小的(a_{x_i})的位置上。这样可以使([1,y_i])间最大的元素位于(y_i),完成归位,而其余的(a_{x_i})所在位置的元素则分别变小了一等。考虑其中一个(a_{x_i})([1,x_i))间大于(a_{x_i})的元素交换后仍大于(a_{x_i})​,逆序对不变。而((x_i,n])间小于(a_{x_i})的元素一定仍小于(a_{x_i}),因为交换后每一位(除去(a_{y_i})​不考虑)只是变小并未变大。不过,当(a_{x_i})中元素出现重复时,需要保证交换后最小的元素位于最前,也就是按(x_i)升序排序。

AC代码

#include<bits/stdc++.h>
using namespace std;
const int N=1010; 
struct node {int x,y;} inv[N*N];
int a[N],n,cnt;
bool cmp(node x,node y) {return x.y>y.y || (x.y==y.y && a[x.x]<a[y.x]) || (x.y==y.y && a[x.x]==a[y.x] && x.x<y.x);}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	for(int i=1;i<=n;i++)
		for(int j=i+1;j<=n;j++) 
			if(a[j]<a[i]) inv[++cnt].x=i,inv[cnt].y=j;
	sort(inv+1,inv+cnt+1,cmp);
	for(int i=1;i<=cnt;i++) swap(a[inv[i].x],a[inv[i].y]);
	bool flag=0;
	for(int i=1;i<=n;i++)
		if(a[i]<a[i-1] && i>1) {flag=1; break;}
	if(flag) {printf("-1"); return 0;}
	printf("%d
",cnt);
	for(int i=1;i<=cnt;i++) printf("%d %d
",inv[i].x,inv[i].y);
	return 0;
}
原文地址:https://www.cnblogs.com/violetholmes/p/15131804.html