樹狀陣列求逆序對

2021-07-25 11:49:55 字數 1605 閱讀 6182

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

知道什麼是逆序對後就好辦了,樹狀陣列的功能就是可以單點更新,區間查詢,這樣你把每個數該在的位置離散化出來,然後每次把每個數該在的位置上加上1,比如乙個數該在的位置為x,那麼用add(x)把這個位置加上1,然後再用區間查詢read(x)查詢1~x的和,也就是可以知道前面有多少個數是比他小的了(包括那個數自己),再用已經插入的數的個數減去read(x),就算出了前面有多少個數比他大了。

下面舉個例子來詳細的看一下過程:

第一次插入的時候把5這個位置上加上1,read(x)值就是1,當前已經插入了乙個數,所以他前面比他大的數的個數就等於 i - read(x) = 1 - 1 = 0,所以總數 sum += 0

第二次插入的時候,read(x)的值同樣是1,但是 i - read(x) = 2 - 1 = 1,所以sum += 1

第三次的時候,read(x)的值是2,i - read(x) = 3 - 2 = 1,所以sum += 1

第四次,read(x)的值是1,i - read(x) = 4 - 1 = 3,所以sum += 3

第五次,

read(x)的值是1,i - read(x) = 5 - 1 = 4,所以sum += 4

這樣整個過程就結束了,所有的逆序對就求出來了。

#include#include#include#include#define ll long long

using namespace std;

int n,tree[100010];

void add(int k,int num)

}int read(int k)

return sum;

}struct node

a[100010];

bool cmp(node a,node b)

int main(void)

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

int cnt = 1;

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

ll sum = 0;

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

printf("%lld\n",sum);

}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行,每行乙個長整型範圍內的...

樹狀陣列 求逆序對

樹狀陣列可以解決線段樹能夠解決的問題,且更加節省空間。線段樹的講解 可以看這位大佬的部落格 樹狀陣列的講解 另一位大佬的部落格 這裡主要寫一下利用樹狀陣列來求解逆序對的個數。簡單來說就是一段序列裡面每個數所在位置之前的位置上比這個數大的數字個數之和。例如 1 2 3 5 4 只有 4 前面的 有乙個...

樹狀陣列求逆序對

題目 分析 計算像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 大...