Ultra-QuickSort (树状数组求逆序数)
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
思路:
假如给的数在1-N范围内,那么我们可以建立一个大小为N+1(避开0)的树状数组,把这列数倒着加入数组,则每次加入一个数的时候我们就可以知道他前面的数(比他小的)有多少个(求区间和),也就是知道了这个数与前面的逆序数,那么每个数与前面数的逆序数之和即为我们要的结果。
但这个题中单个数的大小范围是0到999999999,直接建数组肯定是不可能的,那么我们可以离散化数据,按数的读入顺序标号,则经过排序后数的逆序就转化为了1-N的一列数的逆序数。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int tree[500005];
int N;
int lowbit(int x)
{
return x&(-x);
}
void add(int index,int value)
{
for(int i=index ; i<=N ; i+=lowbit(i))
{
tree[i] += value;
}
}
int getSum(int index)
{
int sum = 0;
for(int i=index ; i>0 ; i-=lowbit(i))
{
sum += tree[i];
}
return sum;
}
struct Node
{
int Value;
int Num;
bool const operator<(const struct Node& a)const
{
return Value<a.Value;
}
}board[500005];
int main(void)
{
while(scanf("%d",&N)&&N)
{
memset(tree,0,sizeof(tree));
for(int i=1 ; i<=N ; i++)
{
scanf("%d",&board[i].Value);
board[i].Num = i;
}
sort(board+1,board+N+1);
long long sum = 0;
for(int i=N ; i>0 ; i--)
{
sum += getSum(board[i].Num);
add(board[i].Num,1);
}
printf("%lld\n",sum);
}
return 0;
}