樹狀陣列 求逆序對

2021-09-11 22:14:47 字數 1159 閱讀 9864

樹狀陣列可以解決線段樹能夠解決的問題,且更加節省空間。

線段樹的講解(可以看這位大佬的部落格):

樹狀陣列的講解(另一位大佬的部落格):

這裡主要寫一下利用樹狀陣列來求解逆序對的個數。

簡單來說就是一段序列裡面每個數所在位置之前的位置上比這個數大的數字個數之和。

例如 1 2 3 5 4

只有 4 前面的 有乙個數字 5 比其大 故構成了乙個逆序對。

而如何求乙個序列中所有逆序對的個數呢?

樹狀陣列可以很好的解決這個問題。首先我們知道樹狀陣列可以利用陣列將我們所需要的數字給儲存起來,並且查詢也很方便。

那麼我們可以這樣操作: 假如序列是:  999  3  56  888

那麼 我們可以首先 給他們編號 如 999--1  3--2   56--3  888--4

那麼 排序(公升序)後 可以看到 序列成為了 2 3 4 1

則 c[2]=1 c[3]= 2 c[4]=3  c[1]=4

c[i] =  a[i-2^k+1]+.....a[i];

(其實也就是將a[i] =1 的過程 -- 也就是將a[i]加入序列  -- a[i]=1 表示加入 =0 表示未加入)

然後我們每次找到 小於  i 的個數, 然後 i 減去這個 數字就是這個當前數字的逆序對數 即 sum += getsum(i);

getsum(i) 求的是 小於 i 的之和 其實就是 小於當前數字的個數 i-getsum(i) 便是 大於當前數字的個數--即逆序對。

補充:編號就可以不需要依賴當前的值,而只需要關注其編號, 其編號根據其鍵值排序後的序列,依次按照當前序列的id加入樹狀陣列,就可以求出逆序對數。

**如下:

#include#include#includeusing namespace std;

struct node a[100000+10];

int b[100000+10];

int cmp(node a,node b)

return sum;

}int main()

sort(a+1,a+n+1,cmp);

for(int i = 1; i<=n; i++)

printf("%d\n",ans);

} return 0;

}

樹狀陣列求逆序對

題目描述 給定乙個陣列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 這兩個就算一對逆序對,簡單來說,所有逆序對的個數和就是找每乙個數的前面有幾個比他的大的數,他們加起來的和就是逆序對的總數。知道什麼是逆序對後就好辦了,...

樹狀陣列求逆序對

題目 分析 計算像a,b這樣上公升的有la對,像c,d這樣下降的有lb對,ans la lb。這樣是有重複的,重複的就是a與c重合,a與d重合,b與c重合,b與d重合這四種情況。那麼減去這四種情況就ok了。可以用樹狀陣列預處理出每一位i的左邊比a i 大的有多少la,少的有多少li,右邊比a i 大...