zoukankan      html  css  js  c++  java
  • 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;
    }
    
    
  • 相关阅读:
    C++ 概念易错点
    C++的位操作符备忘
    C++关键词
    在ubuntu下安装drupal6
    C++符号优先级一览
    开启drupal的clear urls
    VC6.0使用PlaySound函数报错
    小记一下以非string为结束条件的循环
    C++中查看数据类型的方法
    在ubuntu下安装和配置drupal
  • 原文地址:https://www.cnblogs.com/vocaloid01/p/9514176.html
Copyright © 2011-2022 走看看