poj2299

poj2299题目链接

题意:

一个含有n个数的数组, 每次只能交换相邻的两个数, 求最少操作多少次可以使该数组变成一个有序数组(从小到大)。

分析:

先说一下归并排序吧。 二分的思想, 就是将一元素集合分割成两个或更多个子集合,对每一个子集合分别排序,然后将排好序的子集合归并为一个集合。看图理解会好一点!

归并排序核心操作:将一维数组中前后相邻的两个有序序列归并为一个有序序列。

那看一下我们这题, 其实就是在归并排序的过程中顺便计算一下移动次数, 就好了。 举个例子:例如图中前半部分数组{8,3,2,9}, 先分为两部分{8,3} 和{2,9} 。 {8,3}又分为{8} 和{3}, 8又在3前面所以合并8,3需要移动一次 sum= 1, {2,9}分为{2} he {9}, 本来就是有序的所以合并2,9不需要移动 sum= 1; 接下来这一步就该合并{3,8} 和{2,9}了。 2前面有两个比它大的数,所以要交换两次, 2才能排到第一位 sum = sum+2 = 3; 9比前面的都大就不用交换啦 sum= 3。


#include<iostream>
#include<cstdio>
#include<string.h>
#include<algorithm>
using namespace std;

const int N = 500005;
__int64 sum, a[N], c[N];
int n;
void merge1(int low, int high, int mid)
{
    int i = low, j = mid + 1;
    int k = 0;
    while((i <=  mid) && (j <= high))
    {
        if(a[i] <= a[j])
        {
            c[++k] = a[i];
            i++;
        }
        else if(a[i] > a[j])
        {
            c[++k] = a[j];
            j++;
            sum += (mid - i + 1);
        }
    }
    while(i <= mid)
        c[++k] = a[i++];
    while(j <= high)
        c[++k] = a[j++];
    if(low < high)
    {
        for(int i = high; i >= low; i--)
        {
            a[i] = c[k];
            k--;
        }
    }
}
//通过ac()不断将数组划分为更小的区间,再通过merge1()将划分的数组再合并回来, 并且合并的时候使其变得有序
void ac(int low, int high)
{
    if(low < high)
    {
        int mid = (low + high) / 2;
        ac(low, mid);
        ac(mid + 1, high);
        merge1(low, high, mid);
    }
}
int main()
{
    while(scanf("%d", &n) != EOF && n)
    {
        for(int i = 1; i <= n; i++)
            scanf("%I64d", &a[i]);
        sum = 0;
        ac(1, n);
        printf("%I64d\n", sum);
    }
    return 0;
}
时间: 2024-10-31 10:51:16

poj2299的相关文章

线段树求逆序数方法 HDU1394&amp;&amp;POJ2299

为什么线段树可以求逆序数? 给一个简单的序列 9 5 3 他的逆序数是3 首先要求一个逆序数有两种方式:可以从头开始往后找比当前元素小的值,也可以从后往前找比当前元素大的值,有几个逆序数就是几. 线段树就是应用从后往前找较大值得个数.(一边更新一边查) 当前个数是 n = 10 元素   9  5   3 9先加入线段树,T[9]+=1:查从T[9]到T[10]比9大的值,没有sum = 0: 5 加入线段树,T[5] += 1,查从T[5]到T[10]比5大的值,有一个9,sum +=1: 3

POJ2299 Ultra-QuickSort 【树状数组】+【hash】

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

poj2299 二分思想

poj2299   http://poj.org/problem?id=2299题意: 一个含有n个数的数组, 每次只能交换相邻的两个数, 求最少操作多少次可以使该数组变成一个有序数组(从小到大). 分析: 先说一下归并排序吧. 二分的思想, 就是将一元素集合分割成两个或更多个子集合,对每一个子集合分别排序,然后将排好序的子集合归并为一个集合.看图理解会好一点!  归并排序核心操作:将一维数组中前后相邻的两个有序序列归并为一个有序序列. 那看一下我们这题, 其实就是在归并排序的过程中顺便计算一下

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

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

poj2299 Ultra-QuickSort 树状数组求逆序数

poj2299 Ultra-QuickSort   树状数组求逆序数 Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 49587   Accepted: 18153 Description In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequenc

poj2299 Ultra-QuickSort(线段树计数问题)

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

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

poj2299(归并排序求逆序对)

题目链接:https://vjudge.net/problem/POJ-2299 题意:给定一个序列,每次只能交换邻近的两个元素,问要交换多少次才能使序列按升序排列. 思路:本质就是求逆序对.我们用归并排序求逆序对,这也是简单的cdq分治. #include<cstdio> #include<algorithm> #include<cstdlib> #include<cmath> using namespace std; typedef long long

POJ2299题解(树状数组)

POJ2299题解 2019-12-28 Powered by Gauss 1.题目传送门:POJ2299 2.理解题意: 做题的时候,第一步也是最重要的就是理解题意.记住这句话. POJ2299是一道标准的树状数组模板题.题意大致如下: 快速排序是一种非常优秀的排序方式,其精华在于循环比较和swap函数的应用. 先给你一个数N,表示这组数据(没错,这题是多组数据)数的个数,之后的N行,每行一个数Ai 请你输出在快速排序过程中经历的swap函数的次数. 3.算法思路: 树状数组是一种非常高效的数