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

6
0

一开始想着用树状数组,每次输入的时候求比这个数大的数的总和就好了(ans+=i-read(x))后来竟然超时了;

经过了解,知道了必须要离散化

可是我还是不知道数据并不大,为什么要离散化

一,.解释为什么要有离散的这么一个过程?

  1. 刚开始以为999.999.999这么一个数字,对于int存储类型来说是足够了。

  2. 还有只有500000个数字,何必要离散化呢?

  3. 刚开始一直想不通,后来明白了,后面在运用树状数组操作的时候,

  4. 用到的树状数组C[i]是建立在一个有点像位存储的数组的基础之上的,

  5. 不是单纯的建立在输入数组之上。

二,怎么对这个输入的数组进行离散操作?
   离散化是一种常用的技巧,有时数据范围太大,可以用来放缩到我们能处理的范围;
   因为其中需排序的数的范围0---999 999 999;显然数组不肯能这么大;
   而N的最大范围是500 000;故给出的数一定可以与1.。。。N建立一个一一映射;
   (1)当然用map可以建立,效率可能低点;
   (2)这里用一个结构体
   struct Node
   {
      int val,pos;
   }p[510000];和一个数组a[510000];
 
   其中val就是原输入的值,pos是下标;
   然后对结构体按val从小到大排序;
 
   此时,val和结构体的下标就是一个一一对应关系,
   而且满足原来的大小关系;
 
   for(i=1;i<=N;i++)
   a[p[i].pos]=i;
 
   然后a数组就存储了原来所有的大小信息;
   比如 9 1 0 5 4 ------- 离散后aa数组
   就是 5 2 1 4 3; 

ac 代码

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
 
using namespace std;
struct Node{
	int v,id;
}node[500005];
int d[500005],t[500005],n,m,k;
bool cmp(Node a,Node b)
{
	return a.v<b.v;
}
int lowbit(int k)
{
	return (k&(-k));
}

void add(int pos,int v)
{
	while (pos <= 100005)
	{
		d[pos]+=v;
		pos += lowbit(pos);
	}
}
int read(int k)
{
	int sum=0;
	while(k>0){
		sum+=d[k];
		k-=lowbit(k);
	}
	return sum;
}
int main(){

	while(cin>>n)
	{
		if(n==0)break;
		memset(d,0,sizeof(d));
		for(int i=1;i<=n;i++)
		{
			cin>>node[i].v;
			node[i].id=i;
		}
		sort(node+1,node+n+1,cmp);
		for(int i=1;i<=n;i++)   //离散化 
		{
			t[node[i].id]=i;
		}
		long long ans=0;
		for(int i=1;i<=n;i++)
		{
			add(t[i],1);
			ans+=i-read(t[i]);
		}
		cout<<ans<<endl;
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/henu_xujiu/article/details/81234109