5. 逆序对数

问题:

给一列数<a1,a2,......,an>,求它的逆序对,即有多少个有序对(i.j),使得i<j且ai<aj; n 可以高达106

可以采用归并排序的思路

首先将原问题可以分解为两个子问题:对原序列从中间一分为二,分解为两个子序列A,B
两个子问题可以分别递归求解,求得的逆序数分别是na和nb
合并:如果两个子序列A,B分别有序,那么可以在归并过程中求出数对(ai,bj){ai在A中,bj在B中}的逆序数,具体过程如下:
如果ai<bj,则两者没有发生逆序,直接执行归并即可
如果 ai>bj,则发生逆序,ai以及后面的元素都和bj构成逆序
那么这个过程中求得的逆序数和na,nb的和就是原问题的解

#include<iostream>
using namespace std;
int n;
int *a;

int fun(int l, int mid, int r) {
    int cnt = 0;
    for (int i = l; i <= mid; i++)
        for (int j = mid + 1; j <= r; j++)
            if (a[i] < a[j]) cnt++;
    return cnt;
}

int solve(int l, int r) {
    if (l == r) return 0;
    int mid = (l + r) / 2;
    return solve(l, mid) + solve(mid+1, r) + fun(l, mid, r);
}

int main() {
    scanf("%d", &n);
    a = new int[n];
    for (int i = 0; i < n; i++)
        scanf("%d", &a[i]);
    cout << solve(0, n-1) << endl;
    delete[] a;
    return 0;
}

 

posted @ 2019-10-12 17:10  莫莫君不恋爱  阅读(266)  评论(0编辑  收藏  举报