樹狀數組求逆序對

來源:互聯網
上載者:User

標籤:設定   例子   hide   表示   logs   求和   逆序數   要求   lowbit   

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

1、什麼是逆序數?

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

 

2、用樹狀數組求逆序數的總數

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

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

         樹狀數組的插入函數(假設為 void insert(int i,int x) )的含義:在求逆序數這個問題中,我們的插入函數通常使用為insert( i , 1 ),即將數組A[i]的值加1 (A數組開始應該初始化為0,所以也可以理解為設定A[ i ]的值為1,即將數字i 加入到序列的意思 )。,同時維護c數組的值。

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

         所以要求序列中比元素a大的數的個數,可以用i - getsum(a)即可( i 表示此時序列中元素的個數)。

 

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

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

         要想求一個序列 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 1010int 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;}

——來自 熊貓 [http://www.cnblogs.com/xiongmao-cpp/]

樹狀數組求逆序對

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.