POJ 2299 Ultra-QuickSort

来源:互联网 发布:淘宝客定向计划取名 编辑:程序博客网 时间:2024/05/19 13:16

A - Ultra-QuickSort
Time Limit:7000MS    Memory Limit:65536KB    64bit IO Format:%I64d & %I64u
SubmitStatusPracticePOJ 2299

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

树状数组入门应用——求逆序数,话说没做这道题以前我根本就不知道树状数组是个什么东西,做完之后,有了一点感觉。

题目意思是说,用冒泡排序交换的方法对一个序列排序,问需要交换多少次。

那便是一道求逆序数的题,即,若序列i<j,a[i]>a[j],这样的逆序数是几。

写个结构体保存输入时的位置pos.

然后根据值value排序。

构造一个树状数组,序列里每插入一个元素,树状数组就更新一次,统计当前元素前面有多少个元素比自己小,包括自己,则逆序对数为i-sum(re[i])。

查看它前面比它小的已出现过的有多少个数sum,然后用当前位置减去该sum,就可以得到当前数导致的逆序对数了。把所有的加起来就是最后的答案。

除去上面的收获,还接触到了离散化这种方法。

因为题目中0 ≤ a[i] ≤ 999,999,999  n < 500,000 ,内存有限制。这时候就需要离散化登场了。

把原始的数映射为1-n一共n个数,这样就只需要500000个int类型的空间。
#include <stdio.h>#include <algorithm>#include <string.h>#define N 500005using namespace std;typedef struct{        int key,value;}Node;Node a[N];int c[N];int re[N];int n;int lowbit(int x){return x&-x;}int sum(int x){int ret=0;while(x>0)ret+=c[x],x-=lowbit(x);return ret;}void add(int x,int d){while(x<=n){c[x]+=d;x+=lowbit(x);}}bool cmp(Node a,Node b){      return a.value<b.value;}int main(){        while(scanf("%d",&n)>0&&n)        {                for(int i=1;i<=n;i++)                        scanf("%d",&a[i].value),a[i].key=i;                sort(a+1,a+n+1,cmp);                for (int i = 1; i <= n; i++)                        re[a[i].key] = i;                memset(c,0,sizeof(c));                long long ans = 0;                for (int i = 1; i <= n; i++)                {                        add(re[i],1);                        ans += i - sum(re[i]);                }                printf("%I64d\n", ans);        }        return 0;}



0 0