题意:求最少交换次数, 使得序列有序.
解法:用归并排序可求得;
注解: mid-l+1:
r始终是右半侧未交换的第一个值
因为r的前一个已经被交换后r便是第一个未被交换的值
也就是说当前的r为mid的下一个值
code:
/*归并算法*/
#include<iostream>
#include<cstdio>
using namespace std;
const int maxn = 500005;
long long num[maxn], ans, temp[maxn], n;
void Merge(int s, int e){ //将两个有序的序列合并
if(s==e) return ;
int i;
int mid = (s+e)>>1;
int l=s, r=mid+1, k=s;
while(l<=mid&&r<=e){
if(num[l]<=num[r]){
temp[k] = num[l++];//r未改变值
} else {
temp[k] = num[r++];
ans += mid-l+1;//交换次数
//r始终是右半侧未交换的第一个值,
//r的前一个已经被交换后r便是第一个未被交换的值
//也就是说当前的r为mid的下一个值
}
k++;
}
while(l<=mid) temp[k++] = num[l++];
while(r<=e) temp[k++] = num[r++];
for(i=s; i<=e; i++) num[i] = temp[i];
return ;
}
void msort(int s, int e){
if(s>=e) return ;
int mid = (s+e)>>1;
msort(s, mid);
msort(mid+1 , e);
Merge(s, e);
return;
}
int main(){
//freopen("in.txt","r",stdin);
int i, j, k;
while(~scanf("%d", &n), n){
ans=0;
for(i=1; i<=n; i++){
scanf("%lld", &num[i]);
}
msort(1, n);
printf("%lld\n", ans);
}
return 0;
}