HDU2689 Sort it (樹狀陣列求逆序數)

bigbigship發表於2014-07-29
Problem Description
You want to processe a sequence of n distinct integers by swapping two adjacent sequence elements until the sequence is sorted in ascending order. Then how many times it need.
For example, 1 2 3 5 4, we only need one operation : swap 5 and 4.
 

Input
The input consists of a number of test cases. Each case consists of two lines: the first line contains a positive integer n (n <= 1000); the next line contains a permutation of the n integers from 1 to n.
 

Output
For each case, output the minimum times need to sort it in ascending order on a single line.
 

Sample Input
3 1 2 3 4 4 3 2 1
 

Sample Output
0 6

在一個排列中,如果一對數的前後位置與大小順序相反,即前面的數大於後面的數,那麼它們就稱為一個逆序。一個排列中逆序的總數就稱為這個排列的逆序數。逆序數為偶數的排列稱為偶排列,逆序數為奇數的排列稱為奇排列。如2 4 3 1中,(2,1),(4,3),(4,1),(3,1)是逆序,逆序數是4,為偶排列。

也是就說,對於n個不同的元素,先規定各元素之間有一個標準次序(例如n個不同的自然數,可規定從小到大為標準次序),於是在這n個元素的任一排列中,當某兩個元素的先後次序與標準次序不同時,就說有1個逆序。一個排列中所有逆序總數叫做這個排列的逆序數。

如圖14-1所示,用樹狀陣列求逆序數時,陣列A代表數字i是否在序列中出現過,如果陣列i已經存在於序列中,則A[i]=1,否則A[i]=0,此時Query(i)返回值為在序列中比數字i小的元素的個數,假設序列中第i個元素的值為a,那麼前i個元素中比i大的元素的個數為i-Query(a),逆序數的求法也就顯而易見了。

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

const int maxn =1010;

int tree[maxn],n;

int lowbit(int x){
    return x&(-x);
}

void update(int x,int y){
    while(x<=n){
        tree[x]+=y;
        x+=lowbit(x);
    }
}

int query(int x){
    int sum=0;
    while(x>0){
        sum+=tree[x];
        x-=lowbit(x);
    }
    return sum;
}

int main()
{
    while(cin>>n){
        memset(tree,0,sizeof(tree));
        int a,ans=0;
        for(int i=1;i<=n;i++){
            cin>>a;
            update(a,1);
            ans+=i-query(a);
        }
        cout<<ans<<endl;
    }
    return 0;
}


相關文章