zoukankan      html  css  js  c++  java
  • poj2299——Ultra-QuickSort

    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
    

    题意:

    给定一个长度为n(n<=500000)的序列a,如果只允许进行比较和交换相邻两个数的操作,求至少需要多少次交换才能把a从小到大排序。

    Solution:

    容易发现每次交换和比较相邻的两个数使序列有序,就是冒泡排序,而冒泡排序的最少操作数就是序列中的逆序数对的个数,所以本题转换为求序列中的逆序对的个数。于是就可以用树状数组求啦。由于本题数据较大,所以我们需要对数值离散化,然后排序,按倒序update并getsum求在它更新之前有多少个数在其前面,详细见我的树状数组详解的博客。

    代码:

    #include<bits/stdc++.h>
    #define il inline
    #define ll long long
    using namespace std;
    const int N=500005;
    int aa[N],c[N],n;
    struct node{
    int v,order;
    }a[N];
    il bool cmp(node a,node b){return a.v<b.v;}
    il void update(int t,int v)
    {
        while(t<=n){
            c[t]+=v;
            t+=(t&-t);
        }
    }
    il int getsum(int t)
    {
        int sum=0;
        while(t){
            sum+=c[t];
            t-=(t&-t);
        }
        return sum;
    }
    il int gi()
    {
        int a=0;char x=getchar();bool f=0;
        while((x<'0'||x>'9')&&x!='-')x=getchar();
        if(x=='-')x=getchar(),f=1;
        while(x>='0'&&x<='9')a=a*10+x-48,x=getchar();
        return f?-a:a;
    }
    int main()
    {
        while(1){
            n=gi();
            if(!n)return 0;
            memset(c,0,sizeof(c));
            for(int i=1;i<=n;i++)a[i].v=gi(),a[i].order=i;
            sort(a+1,a+n+1,cmp);
            for(int i=1;i<=n;i++)aa[a[i].order]=i;
            ll ans=0;
            for(int i=n;i>0;i--)update(aa[i],1),ans+=getsum(aa[i]-1);
            printf("%lld
    ",ans);
        }
    }
  • 相关阅读:
    方法
    数组
    Scanner类+Random
    运算符2
    运算符1
    Linux中Oracle的安装
    redis安装常见错误
    redis常用命令
    Linux中redis安装
    修改Oracle字符集
  • 原文地址:https://www.cnblogs.com/five20/p/8516198.html
Copyright © 2011-2022 走看看