在網上翻看了一些部落格,感覺大體對於樹狀陣列求逆序對的講解不夠詳細,那些部落格,更多像是給已經學會逆序對的人複習用的。而初學者,可能要冥思苦想。接下來,我便從乙個初學者的角度,來一步步的,講解一下由樹狀陣列求逆序對。需要的前置知識只有,會線段陣列的基本應用。單點更新,區間查詢,求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 這兩個就算一對逆序對,簡單來說,所有逆序對的個數和就是找每乙個數的前面有幾個比他的大的數,他們加起來的和就是逆序對的總數。知道什麼是逆序對後就好辦了,...