POJ Ultra-2299 QuickSort 【离散化+树状数组】

来源:互联网 发布:python的sql注入 编辑:程序博客网 时间:2024/05/14 19:06

Ultra-QuickSort
Time Limit: 7000MS Memory Limit: 65536KTotal Submissions: 55716 Accepted: 20578

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

59105431230

Sample Output

60

Source

Waterloo local 2005.02.05
思路:
这道题问的是给你一个数列,求将数列进行升序排要操作多少次。
首先分析怎么求操作的次数。
例如9 1 0 5 4
先进行第一次排序 0 9 1 5 4 交换了2次,等于0的逆序数。
再进行排序       0 1 9 5 4 交换了1次,等于1的逆序数。
在进行排序       0 1 4 9 5 交换了2次,等于4的逆序数。
在进行排序       0 1 4 5 9 交换了1次,等于1的逆序数。
这样操作的次数为2 + 1 + 2 + 1 = 6,正好等于数列的逆序数和。
每次都要把数列中相对小的数向前移动,因为每次移动都是把小的放到大的前面,有几个大的就要移动几次,这正好是这个数的逆序数。所以,接下来就就是求逆序数了。
可以用两层循环求每一个数的逆序数,但是500,000*500,000会TLE。
主要是解决一个数他前面比他大的个数有几个。
转换一下求前面有多少个数比他小,用树状数组,我们用这个数作为树状数组的下标,每次向下标中放上1,统计他前面共有多少个数,这样就完美的解决了时间复杂度和逆序数的问题。
但是,另外一个问题出现了。如果这个数要是做下标,那么他的范围可是0 <= a[i] <= 999,999,999,所以在进行离散就ok了。

#include <cstdio>#include <set>#include <map>#include <vector>#include <cstring>#include <iostream>#include <algorithm>#define space " "using namespace std;const int MAXN = 500000 + 10;int n, ar[MAXN], b[MAXN], num[MAXN];int sum(int x) {    int s = 0;    while (x >= 1) {        s += num[x];        x -= x&-x;    }    return s;}void add(int x, int y) {    while (x <= n) {        num[x] += y;        x += x&-x;    }}int main() {    while (scanf("%d", &n), n) {        for (int i = 1; i <= n; i++) {            scanf("%d", &ar[i]);            b[i] = ar[i];        }        memset(num, 0, sizeof(num));        sort(b + 1, b + 1 + n); long long ans = 0;        for (int i = 1; i <= n; i++) {            ar[i] = lower_bound(b + 1, b + 1 + n, ar[i]) - b;        }     //   for (int i = 1; i <= n; i++) printf("%d %d\n", i, ar[i]);        for (int i = 1; i <= n; i++) {            add(ar[i], 1);            ans += i - sum(ar[i]);        }        printf("%lld\n", ans);    }    return 0;}


0 0
原创粉丝点击