poj 2299 Ultra-QuickSort 求逆序数,树状数组解法,详细解析

Ultra-QuickSort

Time Limit: 7000MS   Memory Limit: 65536K
Total Submissions: 44554   Accepted: 16195

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

我的AC状态:	

	哈哈,时间连题目要求的十分之一都没到,我对树状数组还是很满意的。
	我先简单的说下树状数组求逆序数的方法,先逆序数定义:点击打开链接
看完逆序数的定义,首先从定义上看,我们其实可以转换一下,有一个序列An,假设其中第i数它后面有Ci比他小的,那逆序数就等于C=C1+C2+...Ci+...Cn,他其实就等价于假设其中第i个数,他前面有Di个比他大的数,D=D1+D2+...+Di+...+Dn=C。这个很容易理解的,相信大家都可以看懂。
接下来大家可能认为结束了,很显然,没结束,想一下树状数组的结构,如果求一个数前面有多少个比他大的,他得一直从1一直遍历到无穷。想想都可怕,所以我们得再转换一下,我们是否可以先求出前i个数中有多少个不大于第i个数的呢?这个很简单,我们只要遍历1->i,就解决了,那好,总共有i个数,假设在它前面有x个不大于第i数的,那比第i个数的大的自然不就出来了么,不就等于i-x-1吗?
	好了,分析到这里,我想大家都应该明白了,我得申明一下,树状数组不能直接求一个含有小于等于0的数的序列的逆序数,
至于为什么不能有负数,你想想,数组的下标能有负的吗?至于为什么不能有0,那是因为树状数组的有个0陷阱,这个自己百度,不多说了。
	不能直接求,但我们可以间接求啊,至于怎么求,我只简单的说一下,转换坐标轴的原点不就可以了吗!!假设10000>Ai>-10000,我们就可以把Ai+10000,得到20000<Ai+10000<0,你看,这样问题是不是就变成我们会的了!我不知道其他人是不是这样处理,这是我自己想的方法,其他人处理的方法估计和我的不会差太多的,毕竟这么简单,
好的,下面是我的代码:

#include <stdio.h>
#include <string.h>
#define MAX 1001000

int t[MAX];
int lowbit(int x)
{
	return x&(-x) ;
}

void update(int pos)
{
	while(pos<MAX)
	{
		++t[pos] ;
		pos += lowbit(pos) ;
	}
}

long long query(int pos)
{
	long long count = 0 ;
	while(pos>0)
	{
		count += t[pos] ;
		pos -= lowbit(pos) ;
	}
	return count ;
}

int main()
{
	int n;
	while(~scanf("%d",&n) && n)
	{
		memset(t,0,sizeof(t)) ;
		long long sum = 0 ;
		for(int i = 0 ; i < n ; ++i)
		{
			int temp ;
			scanf("%d",&temp) ;
			int count = query(temp+1) ;	//防止树状数组的0陷阱
			sum += i-count ;
			update(temp+1) ;
		}
		printf("%I64d\n",sum) ;
	}
	return 0 ;
}

你看,,,是不是比归并排序求逆序数少很多代码,也更容易理解了!

辛辛苦苦码这么多字,,大家多支持一下啦
转载请标明出处
时间: 2024-12-20 10:58:33

poj 2299 Ultra-QuickSort 求逆序数,树状数组解法,详细解析的相关文章

poj 2481 Cows 树状数组解法,详细解析。

Cows Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 13445   Accepted: 4448 Description Farmer John's cows have discovered that the clover growing along the ridge of the hill (which we can think of as a one-dimensional number line) in hi

POJ 2299 Ultra-QuickSort (归并排序求逆序数)

Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 47235   Accepted: 17258 Description In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swappin

poj 2299 Ultra-QuickSort 归并排序求逆序数对

题目链接: http://poj.org/problem?id=2299 题目描述: 给一个有n(n<=500000)个数的杂乱序列,问:如果用冒泡排序,把这n个数排成升序,需要交换几次? 解题思路: 根据冒泡排序的特点,我们可知,本题只需要统计每一个数的逆序数(如果有i<j,存在a[i] > a[j],则称a[i]与 a[j]为逆序数对),输出所有的数的逆序数的和用普通排序一定会超时,但是比较快的排序,像快排又无法统计 交换次数,这里就很好地体现了归并排序的优点.典型的利用归并排序求逆

POJ_3067 Japan[ 逆序数 树状数组 or 归并排序)

传送门:POJ_3067 题目:n,m,k;左右两列数,数的范围分别1-n,1-m,然给k个连线. Sample Input 1 3 4 4 1 4 2 3 3 2 3 1 Sample Output Test case 1: 5 思路:逆序数 代码: //树状数组版 //块状数组 #include<iostream> #include<cstring> #include<cmath> #include<cstdio> #include<algorit

HPU1291 小朋友排队 【逆序数+树状数组】

1291: 小朋友排队 时间限制: 1 Sec  内存限制: 128 MB 提交: 2  解决: 1 [提交][状态][讨论版] [Edit] 题目描述 n 个小朋友站成一排.现在要把他们按身高从低到高的顺序排列,但是每次只能交换位置相邻的两个小朋友. 每个小朋友都有一个不高兴的程度.开始的时候,所有小朋友的不高兴程度都是0. 如果某个小朋友第一次被要求交换,则他的不高兴程度增加1,如果第二次要求他交换,则他的不高兴程度增加2(即不高兴程度为3),依次类推.当要求某个小朋友第k次交换时,他的不高

求逆序对[树状数组] jdoj

求逆序对 题目大意:给你一个序列,求逆序对个数. 注释:n<=$10^5$. 此题显然可以跑暴力.想枚举1到n,再求在i的后缀中有多少比i小的,统计答案即可.这显然是$n^2$的.这...显然过不去,我们思考如何优化?显然,这里的有些过程是重复的.我们将这个序列设为a序列,对于两个1到n中的整数i<j,在j后面的数我们进行了多次重复枚举,我们思考如何优化.容易想到用一个桶来记录.只需要记录对于每一个数来讲,我后面有多少个数是比我小的,只需要将桶中的数累加即可.但是,我们必须记录是这个数之后的桶

hdu 1394 Minimum Inversion Number 逆序数/树状数组

Minimum Inversion Number Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=1394 Description The inversion number of a given number sequence a1, a2, ..., an is the number of pairs (ai, aj) that satisfy i < j and ai

POJ 2299 Ultra-QuickSort(逆序数 树状数组)

Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 45960   Accepted: 16702 Description In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swappin

zoj 3157 Weapon 逆序数/树状数组

B - Weapon Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu Submit Status Description In World War 3, your countries' scientists have invented a special weapon. Assume that the enemy's city can be described by rectangular co

POJ 2299 Ultra-QuickSort(归并排序求逆序对数)

题目地址:POJ 2299 今天下午的多校看来没有白做...实在做不出题闲着无聊看小白鼠学会了个归并排序.哈哈. 归并排序简单地说其实就是先分成一个二叉树直至单个,然后依次从最底层不断进行合并,逆序对数就是在合并的过程中,加入后面的那段中到了比他大的时候,那后面的那些就都是比他大的,都是逆序对数,所以直接加上即可.网上资料很多,就不细说了..用了分治的思想. 自己根据理解写的代码,考虑的太不全面了..又调了好长时间... 代码如下: #include <algorithm> #include