• Ultra-QuickSort (树状数组求逆序数)


    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
    

    思路:
    假如给的数在1-N范围内,那么我们可以建立一个大小为N+1(避开0)的树状数组,把这列数倒着加入数组,则每次加入一个数的时候我们就可以知道他前面的数(比他小的)有多少个(求区间和),也就是知道了这个数与前面的逆序数,那么每个数与前面数的逆序数之和即为我们要的结果。
    但这个题中单个数的大小范围是0到999999999,直接建数组肯定是不可能的,那么我们可以离散化数据,按数的读入顺序标号,则经过排序后数的逆序就转化为了1-N的一列数的逆序数。
    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    int tree[500005];
    int N;
    
    int lowbit(int x)
    {
        return x&(-x);
    }
    
    void add(int index,int value)
    {
        for(int i=index ; i<=N ; i+=lowbit(i))
        {
            tree[i] += value;
        }
    }
    
    int getSum(int index)
    {
        int sum = 0;
        for(int i=index ; i>0 ; i-=lowbit(i))
        {
            sum += tree[i];
        }
        return sum;
    }
    
    struct Node
    {
        int Value;
        int Num;
        bool const operator<(const struct Node& a)const  
        {  
            return Value<a.Value;  
        }  
    }board[500005];
    
    int main(void)
    {
        while(scanf("%d",&N)&&N)
        {
            memset(tree,0,sizeof(tree));
            for(int i=1 ; i<=N ; i++)
            {
                scanf("%d",&board[i].Value);
                board[i].Num = i;
            }
            sort(board+1,board+N+1);
            long long sum = 0;
            for(int i=N ; i>0 ; i--)
            {
                sum += getSum(board[i].Num);
                add(board[i].Num,1);
            }
            printf("%lld
    ",sum);
        }
    
        return 0;
    }
    
    
  • 相关阅读:
    Linux下Vim简单使用
    使用scp命令在Windows和Linux之间拷贝文件
    Linux下使用Crontab实现定时任务
    UOS商店提取软件包离线安装的解决方法
    【50条常用MySQL语句】如果这50条sql语句你都不熟,你别说你会MySQL【建议收藏】
    elasticsearch 7.5.0 windows版本包,已集成ik分词器和pinyin分词器
    Ubuntu安装配置redis
    精讲Mysql各种高难度Sql编写(一)
    Ubuntu离线安装SVN1.13.0(步骤+所需deb安装包)【测试通过】
    Typora提示The beta version of typora is expired, please download and install a newer version.解决办法
  • 原文地址:https://www.cnblogs.com/vocaloid01/p/9514176.html
Copyright © 2020-2023  润新知