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;
}

posted @ 2018-01-21 20:41  Assassin_poi君  阅读(235)  评论(0编辑  收藏  举报