POJ 2299-Ultra-QuickSort(归并排序求相邻元素的交换次数)

Ultra-QuickSort

Time Limit: 7000MS   Memory Limit: 65536K
Total Submissions: 43816   Accepted: 15979

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

题意:给出一个数列,每次交换相邻数字,求排成递增序的最少交换次数。

思路:本应该是冒泡排序求,但是数值为50w,所以铁定会超时。归并排序可以求序列的逆序数,序列的逆序数=在只允许相邻两个元素交换的条件下,得到有序序列的交换次数

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
using namespace std;
int input[500010];
int tmp[500010];
long long sum;
void merge(int l,int mid,int r)
{
    int i=l;
    int j=mid+1;
    int k=1;
    while(i<=mid&&j<=r){//这时候i 和 j 指向的部分都排序完毕了 现在合并
        if(input[i]>input[j]){
            tmp[k++]=input[j++];
            sum+=mid-i+1;////第i个比j大 由于i已经从小到大排过序了 那么i+1到mid的也会比j大
        }
        else
            tmp[k++]=input[i++];
    }
    while(i<=mid)
        tmp[k++]=input[i++];
    while(j<=r)
        tmp[k++]=input[j++];
    for(i=l,k=1;i<=r;i++,k++){
        input[i]=tmp[k];
    }
}
void merge_sort(int l,int r)
{
    if(l<r){//长度大于1  这是个判断不是循环
        int mid=(l+r)/2;
        merge_sort(l,mid);
        merge_sort(mid+1,r);
        merge(l,mid,r);
    }
}
int main()
{
    int n,i;
    while(~scanf("%d",&n)){
            if(n==0)
            break;
        for(i=0;i<n;i++){
            scanf("%d",&input[i]);
        }
        sum=0;
        merge_sort(0,n-1);
        printf("%lld\n",sum);
    }
    return 0;
}
时间: 2024-10-11 08:48:35

POJ 2299-Ultra-QuickSort(归并排序求相邻元素的交换次数)的相关文章

POJ - 2299 Ultra-QuickSort(归并排序)

https://vjudge.net/problem/POJ-2299 题意 求对于给定的无序数组,求出经过最少多少次相邻元素的交换之后,可以使数组从小到大有序. 分析 很明显是求逆序对的数目,那就要想到归并排序了.在归并过程中计算逆序对. #include<iostream> #include<cmath> #include<cstring> #include<queue> #include<vector> #include<cstdio

poj 2299 树状数组求逆序数+离散化

http://poj.org/problem?id=2299 最初做离散化的时候没太确定但是写完发现对的---因为后缀数组学的时候,,这种思维习惯了吧 1.初始化as[i]=i:对as数组按照num[]的大小间接排序 2.bs[as[i]]=i:现在bs数组就是num[]数组的离散化后的结果 3.注意,树状数组中lowbit(i)  i是不可以为0的,0&(-0)=0,死循环... #include <cstdio> #include <cstring> #include

poj 2299 Ultra-QuickSort (归并排序,逆序数)

链接:poj 2299 题意:给出长度为n的序列,每次只能交换相邻的两个元素, 问至少要交换几次才使得该序列为递增序列 分析:冒泡排序每次只能交换相邻两个元素,也就是求 用冒泡排序使其为递增序列的交换次数,每交换一次记录一次就好 但是这题数据较大,冒泡排序效率比较低,会超时的 这里就可以利用归并排序了,用归并排序可以求序列的逆序数, 而一个序列的 逆序数 = 只允许相邻两个元素交换时,得到有序序列的交换次数 #include<stdio.h> #include<stdlib.h>

POJ 2299 Ultra-QuickSort (归并排序)

Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 43446   Accepted: 15822 Description In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swappin

POJ 2299 -Ultra-QuickSort-树状数组求逆序数

POJ 2299Ultra-QuickSort 使用树状数组记录逆序对数. 把数组按照大小顺序插入,getsum(i)就是i前面的比他大的数. 1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 5 using namespace std; 6 7 const int maxn = 500005; 8 int reflect[maxn],c[maxn],N; 9 10 struct Node

求数组元素出现的次数

源码 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> </head> <body> <script> var ary =["丁少","王新","丁少"]; ary.sort(); //给数组按字母排序 var res = [];

POJ 2299 Ultra-QuickSort(归并排序求逆序对数)

题目地址:POJ 2299 今天下午的多校看来没有白做...实在做不出题闲着无聊看小白鼠学会了个归并排序.哈哈. 归并排序简单地说其实就是先分成一个二叉树直至单个,然后依次从最底层不断进行合并,逆序对数就是在合并的过程中,加入后面的那段中到了比他大的时候,那后面的那些就都是比他大的,都是逆序对数,所以直接加上即可.网上资料很多,就不细说了..用了分治的思想. 自己根据理解写的代码,考虑的太不全面了..又调了好长时间... 代码如下: #include <algorithm> #include

poj 2299 Ultra-QuickSort 归并排序求逆序数对

题目链接: http://poj.org/problem?id=2299 题目描述: 给一个有n(n<=500000)个数的杂乱序列,问:如果用冒泡排序,把这n个数排成升序,需要交换几次? 解题思路: 根据冒泡排序的特点,我们可知,本题只需要统计每一个数的逆序数(如果有i<j,存在a[i] > a[j],则称a[i]与 a[j]为逆序数对),输出所有的数的逆序数的和用普通排序一定会超时,但是比较快的排序,像快排又无法统计 交换次数,这里就很好地体现了归并排序的优点.典型的利用归并排序求逆

POJ 2299 Ultra-QuickSort (归并排序求逆序数)

Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 47235   Accepted: 17258 Description In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swappin