题目大意:
给出长度为n的序列,每次只能交换相邻的两个元素,问至少要交换几次才使得该序列为递增序列。
分析:其实就是冒泡排序的过程。但是数据量太大,用冒泡模拟会超时。本题用到归并排序就逆序数:
一个乱序序列的 逆序数 = 在只允许相邻两个元素交换的条件下,得到有序序列的交换次数
由于数字太大,会造成大量内存浪费,使用离散化来压缩空间。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 500005;
struct Node{
int val;
int pos;
};
Node node[N];
int c[N], reflect[N], n;
bool cmp(const Node& a, const Node& b){
return a.val < b.val;
}
int lowbit(int x){
return x & (-x);
}
void update(int x){
while (x <= n){
c[x] += 1;
x += lowbit(x);
}
}
int getsum(int x){
int sum = 0;
while (x > 0){
sum += c[x];
x -= lowbit(x);
}
return sum;
}
int main(){
while (scanf("%d", &n) != EOF && n){
for (int i = 1; i <= n; ++i){
scanf("%d", &node[i].val);
node[i].pos = i;
}
sort(node + 1, node + n + 1, cmp);
for (int i = 1; i <= n; ++i)
reflect[node[i].pos] = i;
for (int i = 1; i <= n; ++i)
c[i] = 0;
__int64 ans = 0;
for (int i = 1; i <= n; ++i){
update(reflect[i]);
ans += i - getsum(reflect[i]);
}
printf("%I64d\n", ans);
}
return 0;
}