51Nod-1019-逆序数

来源:互联网 发布:直播软件tv版 编辑:程序博客网 时间:2024/06/10 21:18

在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。
如2 4 3 1中,2 1,4 3,4 1,3 1是逆序,逆序数是4。给出一个整数序列,求该序列的逆序数。
Input
第1行:N,N为序列的长度(n <= 50000)
第2 - N + 1行:序列中的元素(0 <= A[i] <= 10^9)
Output
输出逆序数
Input示例
4
2
4
3
1
Output示例
4

对于这道题,直接上来的思路就是进行选择对比(类似于选择排序,只不过忽略排序过程),但是只过了七成的数据,所以是不怎么好的,于是乎,了解到,可以用归并排序来做这道题,说到归并排序,最常用的就是用递归来实现,但是其中涉及到一个不断开数组的过程,很有可能会导致题爆掉,所以也是存在很大问题的,所以,想要实现这道题,初步判定需要归并排序,但是要使用非递归实现归并排序,也就是迭代实现。先上递归实现的代码(C):

#include <stdio.h>#define _MAX 50001long ans = 0;//将有序的A[first..mid]和A[mid + 1..last]归并为有序的B[first..last]void Merge(long *A, long *B, int first, int mid, int last){    int i = first, j = mid + 1;    int cur = first;    while (i <= mid && j <= last)    {        if (A[i] <= A[j])        {            B[cur++] = A[i++];        }        else        {            B[cur++] = A[j++];            ans += mid - i + 1; //核心代码,逆序数增加        }    }    while (i <= mid)    {        B[cur++] = A[i++];    }    while (j <= last)    {        B[cur++] = A[j++];    }}//将A[first..last]归并排序为B[first..last]void MSort(long *A, long *B, int first, int last){    int mid;    long BT[_MAX];  //这里存在问题,当数据大时,递归层数多,容易爆掉。    if (first == last)    {        B[first] = A[first];    }    else    {        mid = (first + last) / 2;        MSort(A, BT, first, mid);        MSort(A, BT, mid + 1, last);        Merge(BT, B, first, mid, last);    }    return ;}int main(int argc, const char * argv[]){    int N, i = 1;    long A[_MAX];    scanf("%d", &N);    for (; i <= N; i++)    {        scanf("%ld", &A[i]);    }    MSort(A, A, 1, N);    printf("%ld\n", ans);    return 0;}

这个代码只过了七成的测试数据,不是完美的解题代码,所以接下来要给出真正可行的代码,如下(C):

#include <stdio.h>#include <stdlib.h>#define _MAX 50001long ans = 0;//将有序的A[first..mid]和A[mid + 1..last]归并为有序的B[first..last]void Merge(long *A, long *B, int first, int mid, int last){    int i = first, j = mid + 1;    int cur = first;    while (i <= mid && j <= last)    {        if (A[i] <= A[j])        {            B[cur++] = A[i++];        }        else        {            B[cur++] = A[j++];            ans += mid - i + 1; //核心代码,逆序数增加        }    }    while (i <= mid)    {        B[cur++] = A[i++];    }    while (j <= last)    {        B[cur++] = A[j++];    }}//将A中相邻长度为s的子序列两两归并到B中void MergePass(long *A, long *B, int k, int N){    int i = 1, j;    while (i <= N - 2 * k + 1)    {        Merge(A, B, i, i + k - 1, i + 2 * k - 1);        i = i + 2 * k;    }    if (i < N - k + 1)    {        Merge(A, B, i, i + k - 1, N);    }    else    {        for (j = i; j <= N; j++)        {            B[j] = A[j];        }    }}void MSort(long *A, int N){    long *B = (long *)malloc(sizeof(long) * N);    int k = 1;    while (k < N)    {        MergePass(A, B, k, N);        k *= 2;        MergePass(B, A, k, N);        k *= 2;    }    return ;}int main(int argc, const char * argv[]){    int N, i = 1;    long A[_MAX];    scanf("%d", &N);    for (; i <= N; i++)    {        scanf("%ld", &A[i]);    }    MSort(A, N);    printf("%ld\n", ans);    return 0;}

理论上这种写法是可以AC的,但是不知道为啥,在三组测试数据中出现了运行时错误,一下子整个人都不自在了,25组测试数据,大的过去了,小的也过去了,偏偏是这中不溜的三组数据出现了问题,自己本地测试数据,结果均正确,搞得我不知所以了……

最后经过代码优化,只好写成这样才算是过去了-_-#

#include <stdio.h>#define _MAX 50001long ans = 0;//将有序的A[first..mid]和A[mid + 1..last]归并为有序的B[first..last]void Merge(long *A, long *B, int first, int mid, int last){    int i = first, j = mid + 1;    int cur = first;    while (i <= mid && j <= last)    {        if (A[i] <= A[j])        {            B[cur++] = A[i++];        }        else        {            B[cur++] = A[j++];            ans += mid - i + 1; //核心代码,逆序数增加        }    }    while (i <= mid)    {        B[cur++] = A[i++];    }    while (j <= last)    {        B[cur++] = A[j++];    }}//将A[first..last]归并排序为B[first..last]void MSort(long *A, long *B, int first, int last){    int mid;    if (first < last)    {        mid = (first + last) / 2;        MSort(B, A, first, mid);        MSort(B, A, mid + 1, last);        Merge(A, B, first, mid, last);    }    return ;}int main(int argc, const char * argv[]){    int N, i = 1;    long A[_MAX];    long B[_MAX];    scanf("%d", &N);    for (; i <= N; i++)    {        scanf("%ld", &A[i]);        B[i] = A[i];    }    MSort(A, B, 1, N);    printf("%ld\n", ans);    return 0;}

累死宝宝了!!!OVER!!!

1 0