牛客網 逆序對(歸併排序)

2021-10-13 16:26:58 字數 1119 閱讀 3456

思路:我們知道在歸併排序的逆序對求法中,我們是通過遞迴的方式求解每一段的逆序對,通過這個方法我們似乎可以求解該題,在遞迴的過程中,我們多乙個引數用來表示當前遞迴的是第幾層,而這個層數其實就是我們需要找的qi。我們首先預處理出所有層的逆序對數和順序對數,在查詢時我們需要翻轉所有大小為2^(qi)的塊,由於已經預處理過了,因此直接交換相應層的順序對和逆序對的值即可,但是在交換的過程中我們發現其實所有小於2^(qi)的塊的逆序對數量也等於原順序對數量,因此也是需要交換的。除此之外在求解答案的時候我們也需要將所有層的逆序對數加起來。

#include#include#include#includeusing namespace std;

#define ll long long

#define maxn (1<<20)+5

int n,m,q[maxn],a[maxn],b1[maxn],b2[maxn];

ll rev[maxn],nor[maxn];

void merge(int id,int l,int r,ll nums,int arr)

}nums[id]+=res;

while(i<=mid) a[k++]=arr[i++];

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

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

arr[i]=a[i];

}ll solve(int x)

int main(void)

scanf("%d",&m);

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

scanf("%d",&q[i]);

memset(rev,0,sizeof(rev));

memset(nor,0,sizeof(nor));

merge(n,0,(1<

reverse(b2,b2+(1<

merge(n,0,(1<

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

printf("%lld\n",solve(q[i]));

}return 0;

}

牛客 逆序數 (歸併排序)

題目描述 在乙個排列中,如果一對數的前後位置與大小順序相反,即前面的數大於後面的數,那麼它們就稱為乙個逆序。乙個排列中逆序的總數就稱為這個排列的逆序數。比如乙個序列為4 5 1 3 2,那麼這個序列的逆序數為7,逆序對分別為 4,1 4,3 4,2 5,1 5,3 5,2 3,2 輸入描述 第一行有...

逆序對 (歸併排序)

逆序對的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...