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

链接:poj 2299

题意:给出长度为n的序列,每次只能交换相邻的两个元素,

问至少要交换几次才使得该序列为递增序列

分析:冒泡排序每次只能交换相邻两个元素,也就是求

用冒泡排序使其为递增序列的交换次数,每交换一次记录一次就好

但是这题数据较大,冒泡排序效率比较低,会超时的

这里就可以利用归并排序了,用归并排序可以求序列的逆序数,

而一个序列的 逆序数 = 只允许相邻两个元素交换时,得到有序序列的交换次数

#include<stdio.h>
#include<stdlib.h>
#define M 500000
int a[M+5],l[M+5],r[M+5];
__int64 t;
void cmp(int ll,int mid,int rr)
{
    int m=0,n=0,i,j,k;
    for(i=ll;i<=mid;i++)
        l[m++]=a[i];
    for(i=mid+1;i<=rr;i++)
        r[n++]=a[i];
    i=j=0;
    k=ll;
    while(i<m&&j<n){
        if(l[i]<=r[j])
            a[k++]=l[i++];
        else{
            a[k++]=r[j++];
            t+=m-i;   //计算逆序数
        }
    }
    while(i<m)
        a[k++]=l[i++];
    while(j<n)
        a[k++]=r[j++];
}
void mergesort(int l,int r)
{
    int mid;
    if(l<r){
        mid=(l+r)/2;
        mergesort(l,mid);
        mergesort(mid+1,r);
        cmp(l,mid,r);
    }
}
int main()
{
    int n,i;
    while(scanf("%d",&n)&&n){
        for(i=0;i<n;i++)
            scanf("%d",&a[i]);
        t=0;
        mergesort(0,n-1);
        printf("%I64d\n",t);
    }
    return 0;
}
时间: 2024-10-14 09:43:19

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

poj 2274 The Race(逆序数+线段树)

The Race Time Limit: 15000MS   Memory Limit: 65536K Total Submissions: 3237   Accepted: 664 Case Time Limit: 3000MS Description During the Annual Interstellar Competition for Tuned Spaceships, N spaceships will be competing. Each spaceship i is tuned

AcWing:108. 奇数码问题(归并排序 + 逆序数)

你一定玩过八数码游戏,它实际上是在一个3×3的网格中进行的,1个空格和1~8这8个数字恰好不重不漏地分布在这3×3的网格中. 例如: 5 2 8 1 3 _ 4 6 7 在游戏过程中,可以把空格与其上.下.左.右四个方向之一的数字交换(如果存在). 例如在上例中,空格可与左.上.下面的数字交换,分别变成: 5 2 8 5 2 _ 5 2 8 1 _ 3 1 3 8 1 3 7 4 6 7 4 6 7 4 6 _ 奇数码游戏是它的一个扩展,在一个nn×nn的网格中进行,其中nn为奇数,1个空格和1

Inversion(HDU_4911) 归并排序+逆序数对

Inversion Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 3171    Accepted Submission(s): 1154 Problem Description bobo has a sequence a1,a2,-,an. He is allowed to swap two adjacent numbers f

数据结构 归并排序-逆序数对

逆序对是指数列a[1],a[2],a[3]-中的任意两个数a[i],a[j] (i<j),如果a[i]>a[j],那么我们就说这两个数构成了一个逆序对. 而归并排序的合并两个排列的过程中 会将右边的有序序列的元素依次插入前面的 有序序列 如(3 7 12)   ( 5 6 8) 将5 插入  (3 7 12) 中 因为后面有序 所以 假设   5和左边全部元素构成逆序对  所以有mid+1 而左边序列又有start1 个数比5 小  所以 逆序数就是  mid+1-start1 这样就能大大缩

Frosh Week(HDU_3743)归并排序+逆序数对

Frosh Week Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2772    Accepted Submission(s): 923 Problem Description During Frosh Week, students play various fun games to get to know each other a

归并排序(逆序数问题)详解

微信公众号:bigsai 前言 在排序中,我们可能大部分更熟悉冒泡排序.快排之类.对归并排序可能比较陌生.然而事实上归并排序也是一种稳定的排序,时间复杂度为O(nlogn). 归并排序是基于分治进行归并的,有二路归并和多路归并.我们这里只讲二路归并并且日常用的基本是二路归并.并且归并排序的实现方式有递归形式和非递归形式.要注意其中的区分(思想上没有大的区别,只是划分上会有区分后面会对比). 并且归并排序很重要的一个应用是求序列中的逆序数个数.当然逆序数也可以用树状数组完成,这里就不介绍了. 归并

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(归并排序)

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

归并排序 逆序数

很好理解: int n,a[500010],c[500010]; long long ans; void msort(int L,int R) { if(L==R)return ; int mid=(L+R)>>1; msort(L,mid); msort(mid+1,R); int i=L,k=L,j=mid+1; while(i<=mid&&j<=R) if(a[i]<=a[j]) c[k++]=a[i++]; else c[k++]=a[j++],ans