POJ 2299 树状数组

http://poj.org/problem?id=2299

Description

POJ 2299 树状数组_第1张图片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
本题用到树状数组,由于数字不是连续的,要用到离散化。

#include <iostream>  
#include <stdio.h>  
#include <cmath>  
#include <string.h>
#include <algorithm>  
using namespace std;  
  
int b[500005], c[500005];  
int n;  
  
struct node  
{  
    int num, id;  
}a[500005];  
  
bool cmp(node a, node b)  
{  
    return a.num < b.num;  
}  
  
void update(int i, int x)  
{  
    while(i <= n)  
    {  
        c[i] += x;  
        i += i&(-i);  
    }  
}  
  
int sum(int i)  
{  
    int sum = 0;  
    while(i > 0)  
    {  
        sum += c[i];  
        i -= i&(-i);  
    }  
    return sum;  
}  
  
int main()  
{  
    int i;  
    long long ans;  
    while(scanf("%d", &n), n)  
    {  
        memset(b, 0, sizeof(b));  
        memset(c, 0, sizeof(c));  
        for(i = 1; i <= n; i++)  
        {  
            scanf("%d", &a[i].num); //输入数值num  
            a[i].id = i;            //记录序号id  
        }  
        ///开始离散化  
        sort(a+1, a+n+1, cmp);  //先排序  
        /*因为a[1].num是最小的,id是它的位置,所以b[a[1].id]=1最小, 
          最小的数变成1,第二小的变成2,如此类推从而达到离散化*/  
        b[a[1].id] = 1;  
        for(i = 2; i <= n; i++)  
        {  
            if(a[i].num != a[i-1].num)  
                b[a[i].id] = i;  
            else b[a[i].id] = b[a[i-1].id];  
        }  
        ///离散化完毕  
        ans = 0;  
        for(i = 1; i <= n; i++)  
        {  
            update(b[i], 1);  
            //这里很巧妙,每一次更新后,判断此数比左边的数小的数有多少  
            ans += (sum(n)-sum(b[i]));  
        }  
        //从而求到:右边的数比左边的数大的个数的总和  
        printf("%I64d\n", ans);  
    }  
  
    return 0;  
}  


你可能感兴趣的:(POJ 2299 树状数组)