我是靠谱客的博主 外向小虾米,最近开发中收集的这篇文章主要介绍TJU OJ 1218 Ultra-QuickSort问题描述输入输出解题思路C++代码,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

目录

  • 问题描述
  • 输入
  • 输出
  • 解题思路
  • C++代码

问题描述

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.

输入

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.

5
9
1
0
5
4
3
1
2
3
0

输出

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.

6
0

解题思路

  • 题目要求将一个序列转换为非递减序列,每次交换相邻的两个元素,求最小次数。
  • 非递减序列可以定义为,一个序列中,任取一个数,后面不会出现比它大的数字。
  • 那么想把一个序列变成非递减序列,我们可以首先将最大的数字移到后面,移动的步数是这个最大的数字后面的元素个数。同理,移动第二大的数字到倒数第二位…到这里已经不难看出,其实就是求这个序列的逆序数。
  • 求一个序列的逆序数可以用归并排序,归并排序可以简单描述为左右两边都是一个有序数组(默认从小到大排序,为了方便描述,我把数组称作队列),对左右两边的队头(队头是左右两边的最小元素)进行比较,谁更小就出队放在前面,继续比较队头元素。
  • 融合左右两个队列时,当左边的队头元素比右边的队头元素大的时候,那么左边队列中剩下的其它元素也应该比右边所有元素大。那么逆序数就应该加上左边队列中的元素个数。
  • 因此可以在分治实现归并的同时计算逆序数。

C++代码

#include <iostream>
#include <limits.h>
#define MAX INT_MAX
using namespace std;

int numArray[500005];
long long sum; // 用以记录逆序数 

void MergeSort(int left, int right){
    if(left == right){
        return;
    }
    int mid = (left + right) / 2;
    MergeSort(left, mid);
    MergeSort(mid + 1, right);

    int tempList[500005]; // 暂时用于存储归并排序结果的数组
    int leftNumber = mid - left + 1; // 左边剩余的数字
    int left_index = left, right_index = mid + 1;
    for(int i = left; i <= right; i++){
        if(right_index <= right && left_index <= mid) // 当左右两个游标没有越界的时候
        {
            if(numArray[left_index] > numArray[right_index]){ // 左边的首元素比右边的首元素大,逆序数需要加上左边元素剩余数量
                tempList[i] = numArray[right_index++];
                sum = sum + leftNumber;
            }
            else{
                tempList[i] = numArray[left_index++];
                leftNumber--;
            }
        }
        else if(left_index > mid){ // 左边越界
            tempList[i] = numArray[right_index++];
        }
        else{ // 右边越界
            tempList[i] = numArray[left_index++];
        }
    }
    for(int i = left; i <= right; i++){ // 把排序好的数组copy回去
        numArray[i] = tempList[i];
    }
}

int main(){
    int numCases;
    while(cin >> numCases && numCases){
        sum = 0;
        for(int i = 0; i < numCases; i++){
            cin >> numArray[i];
        }
        MergeSort(0, numCases - 1);
        cout << sum << endl;
    }
    return 0;
}

最后

以上就是外向小虾米为你收集整理的TJU OJ 1218 Ultra-QuickSort问题描述输入输出解题思路C++代码的全部内容,希望文章能够帮你解决TJU OJ 1218 Ultra-QuickSort问题描述输入输出解题思路C++代码所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(43)

评论列表共有 0 条评论

立即
投稿
返回
顶部