Ultra-QuickSort(归并排序记录逆序数)

39 篇文章 0 订阅
1 篇文章 0 订阅
Ultra-QuickSort
点击打开题目链接
Time Limit: 7000MS Memory Limit: 65536K
Total Submissions: 39951 Accepted: 14413

Description

In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swapping two adjacent sequence elements until the sequence is sorted in ascending order. For the input sequence
9 1 0 5 4 ,

Ultra-QuickSort produces the output
0 1 4 5 9 .

Your task is to determine how many swap operations Ultra-QuickSort needs to perform in order to sort a given input sequence.

Input

The input contains several test cases. Every test case begins with a line that contains a single integer n < 500,000 -- the length of the input sequence. Each of the the following n lines contains a single integer 0 ≤ a[i] ≤ 999,999,999, the i-th input sequence element. Input is terminated by a sequence of length n = 0. This sequence must not be processed.

Output

For every input sequence, your program prints a single line containing an integer number op, the minimum number of swap operations necessary to sort the given input sequence.

Sample Input

5
9
1
0
5
4
3
1
2
3
0

Sample Output

6
0

Source


注意,数据比较大,使用long long输入输出;
归并排序:

摘自维基百科:

归并操作的过程如下:

  1. 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
  2. 设定两个指针,最初位置分别为两个已经排序序列的起始位置
  3. 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
  4. 重复步骤3直到某一指针到达序列尾
  5. 将另一序列剩下的所有元素直接复制到合并序列尾

归并排序具体工作原理如下(假设序列共有n个元素):

  1. 将序列每相邻两个数字进行归并操作,形成floor(n/2)个序列,排序后每个序列包含两个元素
  2. 将上述序列再次归并,形成floor(n/4)个序列,每个序列包含四个元素
  3. 重复步骤2,直到所有元素排序完毕
简单的说就是用递归,先把数组左边的元素排好,使其有序,把右边的元素排好使其有序,然后将这两个合并起来,最终将整个数组都是有序的;

不断的递归,就像二分查找一样,故又叫做二路归并排序;

代码:

#include <iostream>
#include<stdio.h>
#define N 500001
using namespace std;
long long a[N],temp[N];
long long sum;
void sortarry(long long int a[],int s,int mid,int e)//合并左右数组集合
{

    int i=s,j=mid+1,m=mid,n=e,k=0;
    while(i<=mid&&j<=n)
    {

        if(a[i]<=a[j])//如果左边的小于右边的,则放到过度数组中
        {
            temp[k++]=a[i++];
        }
        else
        {
            temp[k++]=a[j++];
            sum+=mid-i+1;//记录逆序数因为此时a[i]>a[j],会产生mid+1-i个倒序数(题目要求记录最小的交换次数)
        }
    }
    while(i<=m)
    {
        temp[k++]=a[i++];
    }
    while(j<=n)
        temp[k++]=a[j++];
    for(i=0; i<k; i++)//将过度数组中的元素放到数组的左边
        a[s+i]=temp[i];
}
void arrysort(long long int a[],int s,int e)
{
    if(s<e)
    {
        int mid=(s+e)/2;
        arrysort(a,s,mid);//递归使左边有序
        arrysort(a,mid+1,e);//递归使右边有序
        sortarry(a,s,mid,e);//合并左边和右边
    }
}
int main()
{
    int n,i;
    while(~scanf("%d",&n)&&n)
    {
        sum=0;
        for(i=0; i<n; i++)
            scanf("%I64d",&a[i]);
        arrysort(a,0,n-1);
        printf("%I64d\n",sum);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值