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 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

Waterloo local 2005.02.05

题目链接:http://poj.org/problem?id=2299

题目大意:求逆序数

题目分析:以前学的用树状数组求逆序数,补一下归并排序的求法,感觉实现起来更简单,归并排序自顶向下分解,自底向上合并,每次合并的两个区间都是已经排好序了的,这就给我们求逆序数带来了很大的好处

我们把一个大区间[l,r]分成[l,mid], [mid + 1, r],显然每次我们只要求一个数在左区间,一个数在右区间时的逆序数个数,而不用考虑左区间内和右区间内的逆序数个数,因为合并是自底向上的,左区间和右区间内的逆序数我们已经在他们的子状态中求结果了,所以在自底向上合并时,我们直接累加每一层的逆序数个数就是最后整个区间的逆序数了。很赞的应用,对递归有了更深刻的理解

#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
using namespace std;
int const MAX = 500005;
int a[MAX], n;
ll ans;

void Merge(int l, int mid, int r)
{
    int i = l, j = mid + 1;
    while(i <= mid && j <= r)
    {
        if(a[i] <= a[j])
            i ++;
        else
        {
            j ++;
            //因为左右区间都是有序的,因此a[i]>a[j]说明a[i]~a[mid]都大于a[j]
            ans += mid - i + 1;
        }
    }
    sort(a + l, a + r + 1);
    return;
}

void Merge_sort(int l, int r)
{
    if(l < r)
    {
        int mid = (l + r) / 2;
        Merge_sort(l, mid);
        Merge_sort(mid + 1, r);
        Merge(l, mid, r);
    }
    return;
}

int main()
{
    while(scanf("%d", &n) != EOF && n)
    {
        ans = 0;
        for(int i = 0; i < n; i++)
            scanf("%d", &a[i]);
        Merge_sort(0, n - 1);
        printf("%lld\n", ans);
    }
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-10 01:44:28

POJ 2299 Ultra-QuickSort (归并排序求逆序数)的相关文章

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-树状数组求逆序数

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

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: 38688   Accepted: 13950 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 (求逆序数:离散化+树状数组或者归并排序求逆序数)

Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 55048   Accepted: 20256 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(归并排序求逆序数)

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

poj2299解题报告(归并排序求逆序数)

POJ 2299,题目链接http://poj.org/problem?id=2299 题意: 给出长度为n的序列,每次只能交换相邻的两个元素,问至少要交换几次才使得该序列为递增序列. 思路: 其实就是求逆序数,那么直接向到的就是冒泡了,交换一次,记录一次即可.但是n的范围达到50W,冒泡O(n^2)的复杂度铁定超时. 然后...发现曾经微软有一道笔试题类似就是求逆序数的,对,没错,用归并. 例:合并两个序列(1,3,5)(2,4,6),新序列第二个元素是2,那么它和它前面的3.5形成了逆序数对

HDU 4911 Inversion(归并排序求逆序数)

归并排序求逆序数,然后ans-k与0取一个最大值就可以了. 也可以用树状数组做,比赛的时候可能姿势不对,树状数组wa了.. Inversion Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 578    Accepted Submission(s): 249 Problem Description bobo has a seque