算法學習(二)——樹狀數組求逆序數

1、什麼是逆序數?
2、用樹狀數組求逆序數的總數
         2.1該背景下樹狀數組的含義
         2.2如何使用樹狀數組求逆序數總數
         2.3 C++實現代碼
目錄

 

一、什麼是逆序數?ios

         在一個排列中,若是一對數的先後位置與大小順序相反,即前面的數大於後面的數,那麼它們就稱爲一個逆序。一個排列中逆序數的總數就是這個排列的逆序數。數組

 

二、用樹狀數組求逆序數的總數ide

         2.1該背景下樹狀數組的含義函數

         咱們假設一個數組A[n],當A[n]=0時表示數字n在序列中沒有出現過,A[n]=1表示數字n在序列中出現過。A對應的樹狀數組爲c[n],則c[n]對應維護的是數組A[n]的內容,即樹狀數組c可用於求A中某個區間的值的和。spa

         樹狀數組的插入函數(假設爲 void insert(int i,int x) )的含義:在求逆序數這個問題中,咱們的插入函數一般使用爲insert( i , 1 ),即將數組A[i]的值加1 (A數組開始應該初始化爲0,因此也能夠理解爲設置A[ i ]的值爲1,即將數字i 加入到序列的意思 )。,同時維護c數組的值。code

         樹狀數組中區間求和函數(假設函數定義爲: int getsun(int i ) )的含義:該函數的做用是用於求序列中小於等於數字 i 的元素的個數。這個是顯而易見的,由於樹狀數組c 維護的是數組A的值,則該求和函數便是用於求下標小於等於 i 的數組A的和,而數組A中元素的值要麼是0要麼是1,因此最後求出來的就是小於等於i的元素的個數。blog

         因此要求序列中比元素a大的數的個數,能夠用i - getsum(a)便可( i 表示此時序列中元素的個數)。ci

 

         2.2如何使用樹狀數組求逆序數總數get

         首先來看如何減少問題的規模:string

         要想求一個序列 a b c d,的逆序數的個數,能夠理解爲先求出a b c的逆序數的個數k1,再在這個序列後面增長一個數d,求d以前的那個序列中值小於d的元素的個數k2,則k1+k2即爲序列a b c d的逆序數的個數。

         舉個例子加以說明:

  假設給定的序列爲 4 3 2 1,咱們從左往右依次將給定的序列輸入,每次輸入一個數temp時,就將當前序列中大於temp的元素的個數計算出來,並累加到ans中,最後ans就是這個序列的逆序數個數。

 

序列的變化(下劃線爲新增長元素)

序列中大於新增長的數字的個數

操做

{ }

0

初始化時序列中一個數都沒有

{4 }

0

往序列中增長4,統計此時序列中大於4的元素個數

{4 3 }

1

往序列中增長3,統計此時序列中大於3的元素個數

{4 3 2}

2

往序列中增長2,統計此時序列中大於2的元素個數

{4 3 2 1}

3

往序列中增長1,統計此時序列中大於1的元素個數

         當全部的元素都插入到序列後,便可獲得序列{4 3 2 1}的逆序數的個數爲1+2+3=6.

        

         2.3 C++實現代碼以下:

 

#include <iostream>
#include <string>
using namespace std;
#define N 1010
int c[N]; 
int n;
int lowbit(int i)
{
    return i&(-i);
}
int insert(int i,int x)
{
    while(i<=n){
        c[i]+=x;
        i+=lowbit(i);
    }
    return 0;
}

int getsum(int i)
{
    int sum=0;
    while(i>0){
        sum+=c[i];
        i-=lowbit(i);
    } 
    return sum;
}
void output()
{
    for(int i=1;i<=n;i++) cout<<c[i]<<" ";
    cout<<endl;
}
int main()
{
    while(cin>>n){
        int ans=0;
        memset(c,0,sizeof(c));
        for(int i=1;i<=n;i++){
            int a;
            cin>>a;
            insert(a,1);
            ans+=i-insert(a);//統計當前序列中大於a的元素的個數
        }
        cout<<ans<<endl;
    }
    return 0;
}
相關文章
相關標籤/搜索