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

本文介绍了一种高效算法,用于计算输入序列在进行Ultra-QuickSort排序过程中的逆序对数量。通过使用树状数组和数据离散化技术,在限定的数据范围内实现了快速准确的计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

H - Ultra-QuickSort

Time Limit: 7000 MS Memory Limit: 65536 KB

64-bit integer IO format: %I64d , %I64u Java class name: Main

[Submit] [Status]

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

5
9
1
0
5
4
3
1
2
3
0

Sample Output

6
0

 

题意:

求数据长度为n的数列的逆序对数,数据范围为0-999,999,999。

 

思路:

 

用树状数组求逆序对数时需要一个数组来记录每个数出现的个数,根据题意数组要开999,999,999,显然是不可以的,不过求逆序对数时不必考虑两两数值,只要考虑大小即可,此处利用数据离散化将数组大小缩小到50w就可以存下了。

对样例举例:
          数据:91054    逆序对数为6

   数组下标:12345

      排序后:01459

   数组下标:32541    逆序对数为6

将数据记录到tree[]数组中:

在读取数据的过程中,计算    sum=a[1]+...+a[i-1]
该值为所有比元素i小的数的个数,而i是第i个读入的元素,所以i-sum(i-1)就是逆序对的个数。

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define lowbit(x) x&(-x)
#define LL long long
using namespace std;
LL tree[500005], n;
struct A
{
    LL x, y;
}a[500005];
void add(LL x)
{
    for(LL i=x; i<=n; i+=lowbit(i))
        tree[i] ++;
}
LL getsum(LL x)
{
    LL sum = 0;
    for(LL i=x; i>0; i-=lowbit(i))
        sum += tree[i];
    return sum;
}
bool cmp(struct A a, struct A b)
{
    return a.x < b.x;
}
int main()
{
    while(scanf("%lld", &n) && n)
    {
        memset(tree, 0, sizeof(tree));
        for(int i=1; i<=n; i++)
        {
            scanf("%lld", &a[i].x);
            a[i].y = i;
        }
        sort(a+1, a+1+n, cmp);
        LL ans = 0;
        for(int i=1; i<=n; i++)
        {
            add(a[i].y);
            ans += i-getsum(a[i].y);
        }
        printf("%lld\n", ans);
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值