poj1804 歸併排序求逆序數

2021-06-27 18:49:08 字數 1205 閱讀 6159

逆序數,也就是說,對於n個不同的元素,先規定各元素之間有乙個標準次序(例如n個 不同的自然數,可規定從小到大為標準次序),於是在這n個元素的任一排列中,當某兩個元素的先後次序與標準次序不同時,就說有1個逆序。乙個排列中所有逆序總數叫做這個排列的逆序數。

我們移動元素的次數轉化為,假如對每個數da[i]來說前面比他大的數的數目為c[i]的話,那麼移動元素總次數就應該是c[0]+c[1]+……+c[n-1],就是數列的逆序數。

一般解決有兩種思路。

1、歸併排序,歸併排的話一定是最好的方案,主觀上想一下每乙個數都在向目標位置前進(學過資料結構的話有個名詞叫穩定排序,另乙個穩定排序是冒泡,選擇明顯不是)。

2、用線段樹樹狀陣列來做,求逆序在另一篇博文中有提。

複雜度來說,先說兩種排序,冒泡為o(n^2),歸併o(nlog(n)),樹狀陣列也是o(nlog(n)),

**:#include#include#include#include#include#include#include#include#include#define rep(i,a,b) for(int i=(a);i<(b);i++)

#define rev(i,a,b) for(int i=(a);i>=(b);i--)

#define clr(a,x) memset(a,x,sizeof a)

#define inf 0x3f3f3f3f

typedef long long ll;

using namespace std;

const int mod=1e9 +7;

const int maxn=2005;

const int maxm=4005;

int a[maxn],tmp[maxn];

int ans;

void merge(int l,int m,int r)

else

}while(i<=m)tmp[k++]=a[i++];

while(j<=r)tmp[k++]=a[j++];

for(int i=l;i<=r;i++)

a[i]=tmp[i];

}void merge_sort(int l,int r)

}int main()

{ int t,n,cas=1;

scanf("%d",&t);

while(t--)

{scanf("%d",&n);

for(int i=0;i

求逆序數 逆序數 歸併排序

求排列的逆序數 分治 一 題目描述 總時間限制 1000ms 記憶體限制 65536kb 描述 在internet上的搜尋引擎經常需要對資訊進行比較,比如可以通過某個人對一些事物的排名來估計他 或她 對各種不同資訊的興趣,從而實現個性化的服務。對於不同的排名結果可以用逆序來評價它們之間的差異。考慮1...

歸併排序 求逆序數

首先需要了解逆序對的概念 如果在乙個序列 數列中,滿足 則ax和ay稱為一對逆序對。現在考慮乙個問題 對乙個大小為n 即有n個元素 元素隨機無序且唯一的整數序列中,平均有多少個逆序對?乙個構造證明的方法如下 設乙個隨機無序且元素唯一的整數序列為 我們令lr為l的反向序列,即 然後在lr中任取兩個數,...

歸併排序求逆序數

輸入 n 陣列中元素個數 x 最後所存在的每對逆序對所需要花費的錢 y 按任意順序交換陣列中相鄰兩個元素所要花費的錢 n個陣列中元素 輸出 求使陣列變為公升序所需要的最少 即求該陣列的逆序數 按陣列順序 任意順序交換次數均為該陣列的逆序數次 歸併排序求逆序數 歸併排序採用分治策略 ex 重點在於合併...