您的位置:首页 > 其它

PKU 2299

2010-07-31 17:09 295 查看
Ultra-QuickSort

题型:求逆序数

解法一:正统做法,归并排序,375MS。

#include "stdio.h"
#define N 500000
int num
, temp
;
__int64 sum;

void Merge(int *a, int start, int mid, int end)
{
int i = start, j = mid+1, k = 0;
while (i <= mid && j <= end) {
if (a[i] <= a[j])
temp[k++] = a[i++];
else {
temp[k++] = a[j++];
sum += mid-i+1; //出现逆序时,交换的次数
}
}
while (i <= mid)
temp[k++] = a[i++];
while (j <= end)
temp[k++] = a[j++];
for (i = 0; i < k; i++)
a[start+i] = temp[i];
}

void MergeSort(int *a, int start, int end)
{
int mid;
mid = (end+start) >> 1;
if (start < end) {
MergeSort(a, start, mid);
MergeSort(a, mid+1, end);
Merge(a, start, mid, end);
}
}

int main()
{
int n, i;
while (scanf("%d", &n), n) {
for (i = 0; i < n; i++)
scanf("%d", &num[i]);
sum = 0;
MergeSort(num, 0, n-1);
printf("%I64d\n", sum);
}
return 0;
}


解法二:树状数组,需要先离散化,因为用到qsort(),比归并排序稍慢,516MS。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NL 500000
#define LL long long

struct A {
int a, id;
}q[NL];
int f[NL], p[NL]; //f数组的意义:数字p[i]后边比其小的数的个数。
int n;

int cmp(const void *a, const void *b)
{
return ((struct A *)a)->a - ((struct A *)b)->a;
}

int sum(int idx)
{
int cnt = 0;
while (idx > 0) {
cnt += f[idx];
idx -= idx&(-idx);
}
return cnt;
}

void update(int idx, int c)
{
while (idx <= n) {
f[idx] += c;
idx += idx&(-idx);
}
}

int main()
{
int i;
LL cnt;
while (scanf("%d", &n) != EOF) {
if (!n) break;
for (i=1; i<=n; i++) {
scanf("%d", &q[i].a);
q[i].id = i;
}
qsort(q+1, n, sizeof(q[0]), cmp);
for (i=1; i<=n; i++) {
p[q[i].id] = i;
f[i] = 0;
}
cnt = 0;
for (i=n; i>0; i--) {
cnt += sum(p[i]-1);
update(p[i], 1);
}
printf("%lld\n", cnt);
}
return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: