H - Ultra-QuickSort
Time Limit: 7000 MS Memory Limit: 65536 KB
64-bit integer IO format: %I64d , %I64u Java class name: Main
Description
In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swapping two adjacent sequence elements until the sequence is sorted in ascending order. For the input sequence
9 1 0 5 4 ,
Ultra-QuickSort produces the output
0 1 4 5 9 .
Your task is to determine how many swap operations Ultra-QuickSort needs to perform in order to sort a given input sequence.
Input
The input contains several test cases. Every test case begins with a line that contains a single integer n < 500,000 -- the length of the input sequence. Each of the the following n lines contains a single integer 0 ≤ a[i] ≤ 999,999,999, the i-th input sequence element. Input is terminated by a sequence of length n = 0. This sequence must not be processed.
Output
For every input sequence, your program prints a single line containing an integer number op, the minimum number of swap operations necessary to sort the given input sequence.
Sample Input
5
9
1
0
5
4
3
1
2
3
0
Sample Output
6
0
题意:
求数据长度为n的数列的逆序对数,数据范围为0-999,999,999。
思路:
用树状数组求逆序对数时需要一个数组来记录每个数出现的个数,根据题意数组要开999,999,999,显然是不可以的,不过求逆序对数时不必考虑两两数值,只要考虑大小即可,此处利用数据离散化将数组大小缩小到50w就可以存下了。
对样例举例:
数据:91054 逆序对数为6
数组下标:12345
排序后:01459
数组下标:32541 逆序对数为6
将数据记录到tree[]数组中:
在读取数据的过程中,计算 sum=a[1]+...+a[i-1]
该值为所有比元素i小的数的个数,而i是第i个读入的元素,所以i-sum(i-1)就是逆序对的个数。
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define lowbit(x) x&(-x)
#define LL long long
using namespace std;
LL tree[500005], n;
struct A
{
LL x, y;
}a[500005];
void add(LL x)
{
for(LL i=x; i<=n; i+=lowbit(i))
tree[i] ++;
}
LL getsum(LL x)
{
LL sum = 0;
for(LL i=x; i>0; i-=lowbit(i))
sum += tree[i];
return sum;
}
bool cmp(struct A a, struct A b)
{
return a.x < b.x;
}
int main()
{
while(scanf("%lld", &n) && n)
{
memset(tree, 0, sizeof(tree));
for(int i=1; i<=n; i++)
{
scanf("%lld", &a[i].x);
a[i].y = i;
}
sort(a+1, a+1+n, cmp);
LL ans = 0;
for(int i=1; i<=n; i++)
{
add(a[i].y);
ans += i-getsum(a[i].y);
}
printf("%lld\n", ans);
}
}