Ultra-QuickSort(树状数组+离散化+求逆序)

来源:互联网 发布:mac用什么解压缩软件 编辑:程序博客网 时间:2024/05/29 18:03

Ultra-QuickSort
Time Limit: 7000MS Memory Limit: 65536KTotal Submissions: 62847 Accepted: 23421

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

题意:

给你一个n个整数组成的序列,每次只能交换相邻的两个元素,问你最少要进行多少次交换才能使得整个整数序列上升有序。

思路: 假设当前处理第i个数,我们只需要计算出i的逆序加到总和ans上即可.i的逆序为:在i之前的那些比i大的数的个数.所以从0到n-1一一扫描,令x[v]=1,表示之前的扫描已经有一个值为v的数被扫描到了.所以当我们处理第i个数a[i]的时候,它的逆序为:x[max]+x[max-1]+…+x[a[i]+1]的值( 即为sum(max)-(x[0]+x[1]+…+x[a[i]-1]) ),且我们需要令x[a[i]]++.

        最终可以算出逆序总值ans.

        但是此题的max高达10亿-1,我们不可能去开一个这么大的数组,但是数只有50W个,我们可以开个50W的数组.,而且我们需要的逆序数仅仅相关与数之间的相对大小,比如3,888,1000000 这三个数的序列我们完全可以用1,2,3这三个数的序列代替,他们的逆序数是一样的.

        所以我们将先对读入的数组离散化处理,使得他们的值集中,但是不影响他们之间的相对大小.

然后再用树状数组即可.

代码:

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int MAXN=500000+1000;int c[MAXN];int lowbit(int x){    return x&(-x);}int sum(int x){    int res=0;    while(x>0)    {        res+=c[x];        x -=lowbit(x);    }    return res;}void add(int x,int v){    while(x<=MAXN)    {        c[x]+=v;        x+=lowbit(x);    }}struct node{    int v;    int index;    bool operator <(const node& b)const    {        return v<b.v;    }}nodes[MAXN];int b[MAXN];//将初始数组重新赋值后 ,相对大小不变的新数组int main(){    int n;    while(scanf("%d",&n)==1&&n)    {        for(int i=1;i<=n;i++)        {            scanf("%d",&nodes[i].v);            nodes[i].index=i;  //记录编号。        }        sort(nodes+1,nodes+n+1);        memset(b,0,sizeof(b));        b[nodes[1].index]=1;        for(int i=2;i<=n;i++)  //离散化的过程        {            if(nodes[i].v==nodes[i-1].v)                b[ nodes[i].index ]=b[ nodes[i-1].index ];            else                b[ nodes[i].index ]=i;        }        memset(c,0,sizeof(c));        long long ans=0;        for(int i=1;i<=n;i++)        {            add(b[i],1);//当前扫描的值是b[i],那么在x[b[i]]这个点上加1,表示又出现了1个b[i]值            ans += sum(n)-sum(b[i]);        }        printf("%I64d\n",ans);    }}


阅读全文
0 0
原创粉丝点击