樹狀陣列 求逆序對個數(初學者都能看懂)

2021-10-06 00:00:45 字數 1678 閱讀 4792

在網上翻看了一些部落格,感覺大體對於樹狀陣列求逆序對的講解不夠詳細,那些部落格,更多像是給已經學會逆序對的人複習用的。而初學者,可能要冥思苦想。接下來,我便從乙個初學者的角度,來一步步的,講解一下由樹狀陣列求逆序對。需要的前置知識只有,會線段陣列的基本應用。單點更新,區間查詢,求lowbit。

先貼樹狀陣列的基本**。

求lowbit

int

lowbit

(x)

單點更新

void

update

(int x,

int y,

int n)

區間查詢

int

getsum

(int x)

下面開始正題

逆序對的原理:在一組數中,如果ia[j],則這就是一組逆序對。

我們一般求逆序對的方法,對於每乙個數,求出在它後面的且比它小的數。

**如下:

int ans=0;

for(

int i=

1;i<=n;i++

)}

時間複雜度明顯是n^2的,那能不能有更快的方法呢,就是用樹狀陣列啦。

我們想一想,樹狀陣列能夠解決哪些問題,求某個區間的數的和,我們能不能將求逆序對的問題向這個方向轉化呢?

我們在換一種角度來看看逆序對:對於每乙個數,可能和前面的數形成逆序對,也可能與後面的數形成逆序對。那我們化簡一下,對每個數來說,我們只考慮其作為逆序對中第二個數的逆序對,然後將這樣的逆序對加起來,實際上就是總逆序對個數。為什麼呢,因為每個逆序對有兩個元素,第乙個數,第二個數。我們將逆序對的第二個數的情況都考慮完了,實際上已經考慮完了所有的逆序對。

所以怎麼把它轉化為樹狀陣列的問題呢。

還是舉個例子吧:比如該陣列為 5 3 4 2 1 7

剛開始先插入5,單點更新5這個位置+1,然後查詢區間1到4的數,則逆序對加0個:1-0-1=0(第i個插入-該數前面的數-本身)這個數是在它前面插入並且在它右邊的數,沒錯,這就是以該數為第二個數的逆序對了,在它前面插入的數才會在該數進行計算的時候包含在內。

完整來一遍

插入5,逆序對加(1-0-1)。

插入3,逆序對加(2-0-1)。

插入4,逆序對加(3-1-1)。

插入2,逆序對加(4-0-1)。

插入1,逆序對加(5-0-1)。

插入7,逆序對加(6-5-1)。

**如下。

單點更新

void

update

(int x,

int n)

區間查詢

int

getsum

(int x)

綜合**

//原陣列 

int ap[maxn+1]

=;//樹狀陣列

int c[maxn+1]

=;int ans=0;

for(

int i=

1;i<=n;i++

)

樹狀陣列 求逆序對個數

樹狀陣列求逆序對其實挺簡單的 1.將要求的陣列離散化 離散化將每乙個數的值變為該數在陣列中的大小 inline bool cmp int x,int y for int i 1 i n i a i read p i i sort p 1,p n 1 cmp for int i 1 i n i a p...

樹狀陣列求逆序對

題目描述 給定乙個陣列a,它包含n個整數,分別是a 1 a 2 a n 如果存在下標i和j,使得 i j 且 a i a j 同時成立,則 i,j 就為乙個 逆序對 那麼a陣列總共有多少對不同的 逆序對 輸入格式 1247.in 第一行為n 1 n 100000 接下來是n行,每行乙個長整型範圍內的...

樹狀陣列求逆序對

很久以前就學了樹狀陣列,也知道可以用來求逆序對,然而一直沒弄明白他是怎麼實現的 可能當時沒搞清楚逆序對是什麼吧。逆序對就是如果i j a i a j 這兩個就算一對逆序對,簡單來說,所有逆序對的個數和就是找每乙個數的前面有幾個比他的大的數,他們加起來的和就是逆序對的總數。知道什麼是逆序對後就好辦了,...