逆序對 歸併排序

2021-08-22 14:53:42 字數 3855 閱讀 7965

給定乙個1-n的排列a1, a2, … an,如果ai和aj滿足i < j且ai > aj,我們就稱(ai, aj)是乙個逆序對。

求a1, a2 … an中所有逆序對的數目。

input

第一行包含乙個整數n。

第二行包含n個兩兩不同整數a1, a2, … an。(1 <= ai <= n)

對於60%的資料 1 <= n <= 1000

對於100%的資料 1 <= n <= 100000

output

乙個整數代表答案

sample input

5 3 2 4 5 1

sample output

5網上了解到要用歸併排序(然而歸併排序是個啥}}),交換的次數就是最後的答案,學了兩天,終於寫出來了。注釋還是蠻詳細的。

下面是**:

#include

#include

#include

#include

#include

#include

#include

using

namespace

std;

typedef

long

long ll;

typedef

unsigned

long

long ull;

//#define e 2.718281828459

#define inf 0x7fffffff

#pragma warning(disable:4996)

#define sf scanf

#define pf printf

//#define max(a,b) (a)>(b)?(a):(b);

//#define min(a,b) (a)<(b)?(a):(b);

#define pi acos(-1.0);

#define eps 1e-9;

#define max 1000000+10

#include

void mergesort(int ar, int len, int sum);

void merge(int left, int lena, int right, int lenb, int temp);

ull ans;

int a[100000];

int temp[100000];//記錄每一次的段排序,減去了在link()函式中動態申請的時間

int main(void)

/*system("pause");*/

return0;}

void merge(int left, int left_len, int right, int right_len,int temp)

//錯誤:if( iwhile (i < left_len)

while (j < right_len)

temp[k++] = right[j++];

for (int i = 0; i < left_len + right_len; i++)

}void mergesort(int ar,int len,int sum)

}

#include

#include

#include

#include

#include

#include

#include

using

namespace

std;

typedef

long

long ll;

typedef

unsigned

long

long ull;

#define e 2.718281828459

#define inf 0x7fffffff

#pragma warning(disable:4996)

#define sf scanf

#define pf printf

#define max(a,b) (a)>(b)?(a):(b);

#define min(a,b) (a)<(b)?(a):(b);

#define pi acos(-1.0);

#define eps 1e-9;

#define max 1000000+10

#include

ull ans;

int a[100000];

int temp[100000];//記錄每一次的段排序,減去了在merge()函式中動態申請的時間

void merge(int left, int left_len, int right, int right_len, int temp)

while (i < left_len)

temp[k++] = left[i++];

while (j < right_len)

temp[k++] = right[j++];

for (int i = 0; i < left_len + right_len; i++) //將排序好的段重新輸入原陣列,因為之後temp陣列還要一直變化,直到最後一次即21個元素都排好序時就和原陣列一樣了

left[i] = temp[i];//之前沒有將排序好的段輸入陣列中導致遞迴時temp陣列被改動,無法得到正確結果

}void mergesort(int ar, int len, int sum)

}int main(void)

return

0;}

換個方式:

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

using

namespace

std;

typedef

long

long ll;

typedef

unsigned

long

long ull;

#define e 2.718281828459

#define inf 0x7fffffff

#pragma warning(disable:4996)

#define sf scanf

#define pf printf

#define sf2d(x,y) scanf("%d %d",&(x),&(y))

#define sfd(x) scanf("%d",&x)

#define sff(p) scanf("%lf",&p)

#define pfd(x) printf("%d\n",x)

#define mset(x,b) memset((x),b,sizeof(x))

const

double pi = acos(-1.0);

int ar[100005];

int num[100005];

ll ans = 0;

void dfs(int ar,int len,int num)

while (j < lenl)//重點

num[k++] = ar[j++];

while (i < len)

num[k++] = ar[i++];

for (int i = 0; i < len; i++)

ar[i] = num[i];//儲存

}int main(void)

逆序對 (歸併排序)

逆序對的nlogn方法,改進後的歸併排序 給定排列p,求排列的逆序對數量。p的長度 100000。要求o nlogn 定義歸併排序過程merge l,r merge l,r merge l,mid merge mid 1,r count l,mid,mid 1,r 只需要考慮左右兩段之間造成的逆序對...

歸併排序 逆序對

按照劉汝佳說的,歸併排序分三步 1.劃分問題,即把序列分成元素盡量相等的兩半 2.遞迴求解 3.合併子問題 其實就是把乙個序列不斷的二分,直到只有兩個元素的時候,然後排序,然後返回,再排序。先上 include using namespace std long long a 100005 t 100...

歸併排序(逆序對)

現在我們在競賽中最常用的排序是快速排序,c 只要乙個sort就搞定,但非常明顯,歸併排序的時間複雜度是最優的而且非常穩定,但是人們經常把它用在求逆序對個數上面。那麼下面我用乙個這樣的題來講一下歸併排序。點這裡看題目和樹狀陣列解法。歸併排序是將數列a l,h 分成兩半a l,mid 和a mid 1,...