Ultra-QuickSort(POJ 2299)(离散化加树状数组)

                                                 Ultra-QuickSort

Time Limit: 7000MS Memory Limit: 65536K
Total Submissions: 72891 Accepted: 27322

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

题目链接走起~~~

 

题意介绍:题目是超级快排,实则求对这个数列进行冒泡排序所需要的交换次序,即求逆序数。简单理解:我们可以这样想,求交换多少次  即看这个数前方有多少比他大的即可,分两步具体解释方法:

1.树状数组在本题中的应用

将一个个数插入,在插入过程中我们可以判断,在当前数组中有多少个比他小的数,i - sum(d[i]) 就是有多少比他大的数

i是插入的个数,sum(d[i])比他小的数的个数。

2.什么叫做离散化

百度百科解释。

通俗一点讲就是在存数时防止数据过大过大,而把无限空间中有限的个体映射到有限的空间中去,以此提高算法的时空效率。

具体操作就是不改变数据相对大小 的情况下用小数来代替大数。

例 1  99999999  888   23

-->1       4              3      2

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 500100;

struct nod{
    int val;
    int pos;
}a[maxn];  // 开数组存储其值和位置方便离散化

int n, bit[maxn], d[maxn];
int lowbit(int n)
{
    return n & (-n);
}

bool cmp(nod a, nod b)
{
   return  a.val < b.val;
}
void add(int i, int x)  // 树状数组添加一个数
{
    while(i <= n)
    {
        bit[i] += x;
        i += i & -i;
    }
}
int sum(int i) // 树状数组求取比i小的数的和
{
   int s = 0;
   while(i > 0)
   {
       s += bit[i];
       i -= i & -i;
   }
   return s;
}

int main()
{
    while(scanf("%d", &n) != EOF && n)
    {
        for(int i = 1; i <= n; i++)
        {
            scanf("%d", &a[i].val);
            a[i].pos = i;
        }
        sort(a + 1, a + n + 1, cmp);

        for(int i = 1; i <= n; i++)
        {
            d[a[i].pos] = i;
            bit[i] = 0; // bit数组首先赋值为0,添加数时让他增加看前面有多少比他小的数
        }
        long long ans = 0;
        for(int i = 1; i <= n; i++)
        {
            add(d[i], 1);
            ans += i - sum(d[i]); // 求有多少个比她大的

        }

        printf("%lld\n", ans);
//        cout<<" ----------"<<endl;

    }
    return 0;
}

 

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值