题目描述:
现在给你一个由n个互不相同的整数组成的序列,现在要求你任意交换相邻的两个数字,使序列成为升序序列,请问最少的交换次数是多少?
输入:
输入包含多组测试数据。每组输入第一行是一个正整数n(
n
<
500000
n<500000
n<500000),表示序列的长度,当n=0时。
接下来的n行,每行一个整数a[i](
0
≤
a
[
i
]
≤
999999999
0 \le a[i] \le 999999999
0≤a[i]≤999999999),表示序列中第i个元素。
输出:
对于每组输入,输出使得所给序列升序的最少交换次数。
样例输入:
5
9
1
0
5
4
3
1
2
3
0
样例输出:
6
0
实现代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define lowbit(i) ((i)&(-i))
const int maxn = 5e5 + 10;
int n;
int c[maxn];
int A[maxn];
struct Node {
int val;
int pos;
} temp[maxn];
void update(int x, int v) {
for(int i = x; i <= n; i += lowbit(i)) {
c[i] += v;
}
}
int getSum(int x) {
int sum = 0;
for(int i = x; i > 0; i -= lowbit(i)) {
sum += c[i];
}
return sum;
}
bool cmp(Node a, Node b) {
return a.val < b.val;
}
int main() {
int x;
while(scanf("%d", &n) != EOF) {
if(n == 0) {
break;
}
memset(c, 0, sizeof(c));
memset(A, 0, sizeof(A));
for(int i = 0; i < n; i++) {
scanf("%d", &temp[i].val);
temp[i].pos = i;
}
sort(temp, temp + n, cmp);
A[temp[0].pos]=1;
for(int i = 1; i < n; i++) {
if(temp[i].val != temp[i - 1].val) {
A[temp[i].pos] = i + 1;
} else {
A[temp[i].pos] = A[temp[i - 1].pos];
}
}
long long sum = 0;
for(int i = 0; i < n; i++) {
update(A[i], 1);
sum += getSum(n) - getSum(A[i]);
}
printf("%lld\n", sum);
}
return 0;
}