原题链接:Ultra-QuickSort
题意:给出n个数,求用冒泡排序排成从小到大的序列所交换的次数
思路:本题要求的是逆次序,最容易想到的就是用冒泡排序,时间内是O(n^2)会超时,可以用归并排序或树状数组
//算法复杂度:O(nlogn)
//用树状数组实现,因为a[i]的值范围较大,要对其进行离散化后在用树状数组维护
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
const int MAX_N = 500010;
int n;
int a[MAX_N + 1], b[MAX_N + 1];
int bit[MAX_N];
bool cmp(int x, int y){
if(a[x] != a[y])
return a[x] < a[y];
else
return x < y;
}
int sum(int i) { //求第1到第i项的和
int s = 0;
while(i > 0) {
s += bit[i];
i -= i & -i; //i -= i&-i 也可以写作 i = i&(i-1)
}
return s;
}
void add(int i, int x){ //执行a[i]+=x
while(i <= n){
bit[i] += x;
i += i & -i;
}
}
int main(){
while(scanf("%d", &n) && n){
for(int i = 0;i < n;i ++){
scanf("%d", &a[i]);
b[i] = i;
bit[i + 1] = 0;
}
ll ans = 0;
sort(b, b + n, cmp); //间接排序
for(int i = 0;i < n;i ++) //点离散化
a[b[i]] = i + 1;
for(int j = 0;j < n;j ++){
ans += j - sum(a[j]);
add(a[j], 1);
}
printf("%lld\n", ans);
}
return 0;
}
//归并排序
//算法复杂度:O(nlogn)
#include <stdio.h>
const int MAX_N = 500000;
int n;
int a[MAX_N + 1], b[MAX_N + 1];
long long count;
void Merge(int sourceArr[],int tempArr[], int startIndex, int midIndex, int endIndex)
{
int i = startIndex, j = midIndex + 1, k = startIndex;
while(i < midIndex + 1 && j < endIndex + 1)
{
if(sourceArr[i] > sourceArr[j]){
tempArr[k++] = sourceArr[j++];
count += midIndex - i + 1; //记录逆次序
}
else
tempArr[k++] = sourceArr[i++];
}
while(i < midIndex + 1)
tempArr[k++] = sourceArr[i++];
while(j < endIndex + 1)
tempArr[k++] = sourceArr[j++];
for(i = startIndex; i <= endIndex; i++)
sourceArr[i] = tempArr[i];
}
//内部使用递归
void MergeSort(int sourceArr[], int tempArr[], int startIndex, int endIndex)
{
int midIndex;
if(startIndex < endIndex)
{
midIndex = (startIndex + endIndex) / 2;
MergeSort(sourceArr, tempArr, startIndex, midIndex);
MergeSort(sourceArr, tempArr, midIndex + 1, endIndex);
Merge(sourceArr, tempArr, startIndex, midIndex, endIndex);
}
}
int main(){
while(scanf("%d", &n) && n){
for(int i = 0;i < n;i ++)
scanf("%d", &a[i]);
count = 0;
MergeSort(a, b, 0, n - 1);
printf("%lld\n", count);
}
return 0;
}