逆序对的两种求法
Posted emcikem
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了逆序对的两种求法相关的知识,希望对你有一定的参考价值。
逆序对
对于一个数论(a_{1},a_{2}......a_{n}),定义有一对序列({i,j}),当且仅当(i<j)且(a_{i}>a_{j})为逆序对
归并排序
归并排序是基于分治思想进行的,把区间([l,r])拆分成([l,mid])和([mid+1,r])两部分,分治下去进行排序,每次合并的复杂度就是当前[l,r]的长度,进行(log_{2}n)次分治,总长度为n,则
归并排序的复杂度为(O(nlog_{2}n))
归并排序写法
void MergeSort(int l,int r){
if(l == r)return;
int mid = (l + r) >> 1;
MergeSort(l, mid);//左边
MergeSort(mid+1,r);//右边
int i = l,j = mid + 1, t = l;//i是左边的,j是右边的
while(i <= mid && j <= r){
if(a[i] <= a[j])b[t++] = a[i++];//左边小
else b[t++] = a[j++];
}
while(i <= mid)b[t++] = a[i++];//右边部分多
while(j <= r)b[t++] = a[j++];//左边部分多
for(int k = l;k <= r; k++)a[k] = b[k];//及时更新
}
而对于求逆序对,由于合并所以左边和右边都是一组有序的数论。
左区间中剩下没加入的合并元素部分的一定就比右区间大
所以,在
else b[t++] = a[j++];
部分加一个ans += mid-i+1
则基于归并排序的求逆序对模板为
void MergeSort(int l,int r){
if(l == r)return;
int mid = (l + r) >> 1;
MergeSort(l, mid);//左边
MergeSort(mid+1,r);//右边
int i = l,j = mid + 1, t = l;//i是左边的,j是右边的
while(i <= mid && j <= r){
if(a[i] <= a[j])b[t++] = a[i++];//左边小
else b[t++] = a[j++],ans += mid - i + 1;
}
while(i <= mid)b[t++] = a[i++];//右边部分多
while(j <= r)b[t++] = a[j++];//左边部分多
for(int k = l;k <= r; k++)a[k] = b[k];//及时更新
}
树状数组
以上是关于逆序对的两种求法的主要内容,如果未能解决你的问题,请参考以下文章