對於逆序數通俗的理解:對於序列中每個位置的的數,其之前比他的值大的個數之和,或者在其之後比他的值小的個數之和,如此稱為逆序數。
實現手段:線段樹、樹狀陣列、離散化、歸併排序、列舉
int ans =0;
//逆序數個數
int num[maxn]
;for
(int i =
1; i < n; i++)}
}
#include
using
namespace std;
int a[
100005];
//儲存有多少比它大的數字在它之前
intmain()
} cout << sum << endl;
}
細節
關於sum的含義是求得1~idx下標得字首和,在這裡根據方法2得思路就是rank <= idx的字首數量,這裡就要利用到一點容斥的思想:我們的目標是考慮當前有多少個比當前數排名大的數,當前全集為i,rank <= idx的數量為sum(idx),則當前 rank > idx 的數量為i-sum(idx)。其實c維護的就是rank的數量。舉例:
目前資料集
目前下標得到的逆序數
說明初始化
逆序數為0,資料集為空
0加入7,排名為4,逆序數為0,前面沒有排名比他高的數字
1加入4,排名為2,逆序數為1,前面排名有1個比他高的數字,分別為7
2加入3,排名為1,逆序數為2,前面排名有2個比他高的數字,分別為7,4
0加入8,排名為5,逆序數為0,前面排名有0個比他高的數字
2加入6,排名為3,逆序數為2,前面排名有2個比他高的數字,分別為7,8
觀察c陣列的變化
("\n\n排列的逆序數為 = %lld\n"
,sum);}
return0;
}
#include
#include
using
namespace std;
const
int maxn =
(int
)1e5+5
;typedef
long
long ll;
typedef
double db;
typedef
long
double ldb;
int val[maxn]
,tmp[maxn]
;ll cnt;
void merge (
int l,
int m,
int r)
else
}while
(i <= m)
while
(j <= r)
for(
int i = l; i <= r; i++)}
void
mergesort
(int l,
int r)
return;}
intmain()
cnt =0;
mergesort(1
, n)
; cout << cnt <<
'\n'
;return0;
}
分治遞迴逆序數 逆序數的分治演算法
給我們乙個序列,讓我們求其逆序數 如3 2 1 4 逆序數為 2 1 0 0 3 我們這樣定義乙個序列的逆序數 序列a1 a2 a3 a2 an 這個序列的逆序數c,等於a1,a2.的逆序數的和.即 c sum ci ci為滿足ai aj j i 的數的總的個數,即ci sum ai aj j i ...
分治遞迴逆序數 歸併演算法經典應用 求解逆序數
原創不易,求個關注 在之前介紹線性代數行列式計算公式的時候,我們曾經介紹過逆序數 我們在列舉出行列式的每一項之後,需要通過逆序數來確定這一項符號的正負性。如果有忘記的同學可以回到之前的文章當中複習一下 線性代數精華1 從行列式開始 如果忘記呢,問題也不大,這個概念比較簡單,我想大家很快就能都搞清楚。...
求逆序數的分治演算法
給我們乙個序列,讓我們求其逆序數 如3 2 1 4 逆序數為 2 1 0 0 3 我們這樣定義乙個序列的逆序數 序列a1 a2 a3 a2 an 這個序列的逆序數c,等於a1,a2.的逆序數的和.即 c sum ci ci為滿足ai aj j i 的數的總的個數,即ci sum ai aj j i ...