HRBUST 2224 逆序對數(樹狀陣列)

2021-08-17 20:45:18 字數 1813 閱讀 9474

給定 n 個數組成的陣列,求其逆序對的總數。

逆序對定義為,存在 (i, j) 滿足 i < j 且 a[i] > a[j] 的二元組的數目。

第一行包含乙個整數,表示陣列的項數。

接下來的一行,包含 n 個數(2 <= n <= 100000),依次表示 a[i](a[i] <= 10^9)。

輸出一行表示對應的答案。。

1 3 2 5 4

對於乙個從左往右的序列的,我們可以這樣來統計逆序對數

考慮與前面已經出現的數可能出現逆序

那第乙個數肯定無法構成逆序對

對於第二數 我關注第1個數

對於第三個數 我關注1~2個數

那可以對於每個數 先做個a[i]+1 ~n的查詢 (維護乙個區間和)即這麼多數之前有沒有出現過(但開乙個陣列v記錄)

然後把v[a[i]]++

但發現到數的範圍可能會很大

但是數量是1e5

於是想到離散化

即對於逆序對數 我只關注這些數之間的相對大小關係 辣我排個序搞一下就行

(可以用pair記一下之前的id

也可以只排序再二分定位 )

注意使用long long 逆序對數最大是n2

n

2左右的

//求逆序對數 注意離散化

#include

#include

using

namespace

std;

const

int maxn=1e5+10;

typedef pair pir;

typedef

long

long ll;

int node[maxn];

int a[maxn];

pir b[maxn];//輔助陣列

int n;

inline

int lowbit(int x)

void add(int a,int b)

}ll sum(int n)//字首和

return res;

}int main()

sort(b+1,b+n+1);

int k=1;

a[b[1].second]=k;//離散化後的值

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

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

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

cout

0;}

//求逆序對數 注意離散化

#include

using

namespace

std;

const

int maxn=1e5+10;

typedef

long

long ll;

int node[maxn];

int a[maxn];

int b[maxn];//輔助陣列

int n;

inline

int lowbit(int x)

void add(int a,int b)

}ll sum(int n)//字首和

return res;

}int main()

sort(b+1,b+n+1);

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

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

cout

0;}

尋找逆序對

設a 1.n 是乙個包含n個不同數的陣列。如果在ia j 則 i,j 就成為a中的乙個逆序對 inversion 要確定乙個陣列中的逆序對的個數,可以採取分治法。將a分為兩部分a1和a2,則a中逆序對的數目等於a1中逆序對的數目 a2中逆序對的數目和a1,a2合併時a1中比a2中元素大的數目。inc...

逆序對問題

逆序對問題。給一列數a1 a2,an 求它的逆序對數,即有多少個有序對 i j 使得 i j 但ai aj n 可以高達106 由於 n 的數量級到了106 所以採用o n2 及以上的時間複雜度肯定會超時,所以必須選取o nlog 2n 及以下時間複雜度的演算法。逆序對的求解思路和歸併排序很像,嘗試...

動態逆序對

容易寫掛 對於新手與蒟蒻 洛谷 cdq 如果按照三維偏序那樣求,那麼會漏掉一些情況。所以要跑兩遍cdq。兩遍cdq又會有乙個問題,就是判等於的問題。第一遍cdq第三維判等於,第二遍判不等於.include define ll long long using namespace std inline ...