题目大意:
现有多个测例,每个测例都给出一个长度为n(n < 500,000)的整数序列,每个元素的范围为0 ≤ ai ≤ 999,999,999,测例以n = 0结束,对于每个测例打印出序列的逆序数的个数。
注释代码:
/*
* Problem ID : POJ 2299 Ultra-QuickSort
* Author : Lirx.t.Una
* Language : C
* Run Time : 594 ms
* Run Memory : 9344 KB
*/
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <map>
//序列最大长度
#define MAXN 500000
using namespace std;
typedef __int64 llg;
struct Num {//表示序列中的每个数字
int v;//数字的值
int p;//数字在序列中的位置
bool
operator<(const Num &oth)
const {//从小到大排序
return v < oth.v;
}
};
Num ori[MAXN];//原序列
int ram[MAXN];//乱序序列
int c[MAXN];//树状数组求逆序数
int lowbit[MAXN];
int n;//序列长度
void
update(int x) {
while ( x <= n ) {
c[x]++;
x += lowbit[x];
}
}
int
query(int x) {
int sum;
sum = 0;
while ( x > 0 ) {
sum += c[x];
x -= lowbit[x];
}
return sum;
}
int
main() {
int i;//计数变量
llg ans;//最终逆序数个数
for ( i = 1; i < MAXN; i++ ) lowbit[i] = i & -i;
while ( scanf("%d", &n), n ) {
memset(c, 0, sizeof(c));
for ( i = 0; i < n; i++ ) {
ori[i].p = i;
scanf("%d", &ori[i].v);
}
sort(ori, ori + n);//离散化,排列前p的顺序从0 ~ n
//排序后,p成乱序了(也包含0 ~ n),其实就是相当于求p乱序序列中的逆序数
//因此就自然地将原序列离散化了,并且映射在了一个较小的区间上(0 ~ n)
//使得树状数组规模变小,因此就不需要unique来进行离散化了,省时间,unique会超时,不离散化会超内存!!
for ( i = 0; i < n; i++ ) ram[ ori[i].p ] = i + 1;
ans = 0;
for ( i = 0; i < n; i++ ) {
update( ram[i] );
ans += i + 1 - query( ram[i] );
}
printf("%I64d\n", ans);
}
return 0;
}
无注释代码:
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#define MAXN 500000
using namespace std;
typedef __int64 llg;
struct Num {
int v;
int p;
bool
operator<(const Num &oth)
const {
return v < oth.v;
}
};
Num ori[MAXN];
int ram[MAXN];
int c[MAXN];
int lowbit[MAXN];
int n;
void
update(int x) {
while ( x <= n ) {
c[x]++;
x += lowbit[x];
}
}
int
query(int x) {
int sum;
sum = 0;
while ( x > 0 ) {
sum += c[x];
x -= lowbit[x];
}
return sum;
}
int
main() {
int i;
llg ans;
for ( i = 1; i < MAXN; i++ ) lowbit[i] = i & -i;
while ( scanf("%d", &n), n ) {
memset(c, 0, sizeof(c));
for ( i = 0; i < n; i++ ) {
ori[i].p = i;
scanf("%d", &ori[i].v);
}
sort(ori, ori + n);
for ( i = 0; i < n; i++ ) ram[ ori[i].p ] = i + 1;
ans = 0;
for ( i = 0; i < n; i++ ) {
update( ram[i] );
ans += i + 1 - query( ram[i] );
}
printf("%I64d\n", ans);
}
return 0;
}