POJ 2299 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

扫描二维码关注公众号,回复: 2851695 查看本文章
6
0

题意:

通过交换两两交换, 问多少次交换过后, 会形成一个递增序列。

思路:

题目的意思可以转化成求逆序对个数的过程。

求逆序对的话可以通过线段树,一边查询一边插入线段数, 但是这个题目给出的元素数目太大, 需要离散化, 因为给出的元素个数最多为500000个, 所以可以通过求元素在数组中的编号大小进行离散化。

代码如下:
 

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
const int maxn=500005;
int n;
struct data
{
    int dat;
    int no;
};
data d[maxn];
int tree [maxn<<2];
//离散化数组
int a[maxn];
void pushup (int re)
{
    tree[re]=tree[re<<1]+tree[re<<1|1];
}
//sort函数
int compare (data a,data b)
{
    return a.dat<b.dat;
}
void build (int l,int r,int re)
{
    tree[re]=0;
    if(l==r)
        return;
    int mid=(l+r)>>1;
    build (l,mid,re<<1);
    build (mid+1,r,re<<1|1);
}
int query (int l,int r,int re,int left,int right)
{
    if(l>=left&&r<=right)
        return tree[re];
    int ans=0;
    int mid=(l+r)>>1;
    if(mid>=left)
        ans+=query (l,mid,re<<1,left,right);
    if(mid<right)
        ans+=query (mid+1,r,re<<1|1,left,right);
    return ans;
}
void update (int l,int r,int re,int loc)
{
    if(l==r)
    {
        tree[re]++;
        return;
    }
    int mid=(l+r)>>1;
    if(loc<=mid)
    update (l,mid,re<<1,loc);
    else
    update (mid+1,r,re<<1|1,loc);
    pushup(re);
}
int main()
{
    while (scanf("%d",&n)!=EOF&&n)
    {
        //记录下元素的编号
        for (int i=1;i<=n;i++)
        {
            scanf("%d",&d[i].dat);
            d[i].no=i;
        }
        //排序
        sort (d+1,d+n+1,compare);
         int num=1;
         //离散化
        for (int i=1;i<=n;i++)
        {
            if(i>1&&d[i].dat==d[i-1].dat)
              a[d[i].no]=a[d[i-1].no];
            else
              a[d[i].no]=num++;
        }
        //建树
        build (1,n,1);
        long long int sum=0;
        for (int i=1;i<=n;i++)
        {
            sum+=query (1,n,1,a[i]+1,n);
            update (1,n,1,a[i]);
        }
        printf("%lld\n",sum);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41410799/article/details/81711408