关于归并逆序对

P1908 逆序对

Kniqht @ 2023-09-12 21:04:01

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+10;
int n,a[N],tmp[N],cnt;
void merge_sort(int q[],int l,int r){
    if(l>=r) return;
    int mid=l+r>>1;
    merge_sort(q,l,mid);
    merge_sort(q,mid+1,r);
    int i=l,j=mid+1,k=0;
    while(i<=mid&&j<=r){
        if(q[i]<=q[j]) tmp[++k]=q[i++];
        else tmp[++k]=q[j++],cnt+=mid-i+1;
    }
    while(i<=mid) tmp[++k]=q[i++];
  //这里为什么不会产生逆序对呢?cnt为什么不需要加上j-(mid+1)+1呢??
    while(j<=r) tmp[++k]=q[j++];
    for(i=l,j=1;i<=r;i++,j++) q[i]=tmp[j];
}
signed main(){
    scanf("%lld",&n);
    for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    merge_sort(a,1,n);
    printf("%lld",cnt);
    return 0;
}// 

by ZhangJiahao0918 @ 2023-09-12 21:25:51

@qi136

这里左右两个区间都是有序的,因此第一个while中在找到q_i>q_j的时候已经计算了[i,mid]这个区间内与q_j的逆序对数量,后面的for循环只是排序


by zzs2731 @ 2023-09-12 21:30:49

在归并排序的过程中,最后剩下的只有3种情况:

1.剩下左区间未合并

2.剩下右区间未合并

3.左右区间都合并完成

不会出现左右两个区间均有剩余的情况

所以不会出现逆序对

(因为逆序对的产生是由右区间在左区间前会产生剩余左区间未合并元素个数个逆序对)

本蒟蒻的见解


by Kniqht @ 2023-09-13 05:47:12

@ZhangJiahao0918 @zzs2731 谢谢大佬门!我想明白了!


|