题意:
给你一串序列,每次只能交换序列中相邻的数字,问最少需要操作几次能将序列变成有序的。
思路:
本题从逆序对出发思考,可以发现,交换一对相邻数字最多只能减少一对逆序对。
因此不难想到,本题的最少操作数就是所有逆序对个数。
此类问题还有很多,比如取区间中的一段连续数字插入数列中任意位置,需要多少次可以让数列变成有序数列。
此时就需要考虑每一次插入,最多可以改变几个数字的后继,和本题也是一样的思考方式。
代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define rep(i,a,b) for(int i = a;i <= b;i++)
using namespace std;
const int N = 1500;
int a[N],cnt,tmp[N];
void Merge(int l,int mid,int r)
{
//合并a[l-mid]与a[mid+1-r]
int i = l, j = mid+1;
rep(k,l,r)
if(j > r || (i <= mid && a[i] <= a[j])) tmp[k] = a[i++]; //此处是<还是<=,取决于题意,即5,5是否算一对逆序对
else tmp[k] = a[j++], cnt += mid-i+1;
rep(k,l,r) a[k] = tmp[k];
}
void Mergesort(int l,int r)
{
if(l < r)
{
int mid = (l+r)>>1;
Mergesort(l,mid);
Mergesort(mid+1,r);
Merge(l,mid,r);
}
}
int main()
{
int T;
scanf("%d",&T);
rep(cas,1,T)
{
cnt = 0;
int n;
scanf("%d",&n);
rep(i,1,n)
scanf("%d",&a[i]);
Mergesort(1,n);
printf("Scenario #%d:\n%d\n\n",cas,cnt);
}
return 0;
}