Codeup墓地-1098
src:http://codeup.cn/problem.php?id=1098
1098: 最少的交换
时间限制: 1 Sec 内存限制: 32 MB
题目描述
现在给你一个由n个互不相同的整数组成的序列,现在要求你任意交换相邻的两个数字,使序列成为升序序列,请问最少的交换次数是多少?
输入
输入包含多组测试数据。每组输入第一行是一个正整数n(n<500000),表示序列的长度,当n=0时。
接下来的n行,每行一个整数a[i](0<=a[i]<=999999999),表示序列中第i个元素。
输出
对于每组输入,输出使得所给序列升序的最少交换次数。
样例输入
5
9
1
0
5
4
3
1
2
3
0
样例输出
6
0
//归并排序,结果A也是从小到大排好序的
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
vector<int> A;
int N;
ll merge_count(vector<int> &a){
int n=a.size();
if(n<=1){
return 0;
}
ll cnt =0;
vector<int> b(a.begin(),a.begin()+n/2);
vector<int> c(a.begin()+n/2,a.end());
cnt+=merge_count(b);
cnt+=merge_count(c);
//此时b和c已经分别排好序了
int ai=0,bi=0,ci=0;
//合并两部分并计算逆序数
while(ai<n){
if(bi<b.size()&&(ci==c.size()||b[bi]<=c[ci])){
a[ai++]=b[bi++];
}
else{
//逆序数计算
//如若bi>ci,则这在B序列中从bi开始到结束的数都比ci大
//这些数的数量为n/2-bi
cnt+=n/2-bi;
a[ai++]=c[ci++];
}
}
return cnt;
}
int main(){
int c;
while(cin>>N&&N){
for(int i=0;i<N;i++){
scanf("%d",&c);
A.push_back(c);
}
printf("%lld\n",merge_count(A));
A.clear();
}
return 0;
}