poj-2299-Ultra-QuickSort(树状数组,离散化+逆序数)

题目链接:http://poj.org/problem?id=2299

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

Source

Waterloo local 2005.02.05

题目大意:给出一个有n个元素的无序的数列,将他排成升序的数列需要多少步,一次只能交换相邻的元素(类似冒泡排序),数据范围是0 ≤ a[i] ≤ 999,999,999。

说是类似冒泡排序,但是肯定不能用冒泡排序啊,那么陋(其实是会超时。。。),直接用树状数组的话要开的数组太大了,money limit。。因此我么要将他离散化处理一下,什么是离散化呢?其实一点都不高深,例:

1 9 5 6 4,离散化后就是

1 5 2 4 3,相当于微经(微观经济学)里面的序数效用论(学过经济学就是为所欲为23333)

大白话:就是将他范围缩减,顺序不变

所以就可以直接求逆序数了:

ac:

#include<stdio.h>
#include<string.h>  
#include<math.h>  
  
//#include<map>   
//#include<set>
#include<deque>  
#include<queue>  
#include<stack>  
#include<bitset> 
#include<string>  
#include<iostream>  
#include<algorithm>  
using namespace std;  

#define ll long long  
#define INF 0x3f3f3f3f  
#define mod 1000000007
#define clean(a,b) memset(a,b,sizeof(a))// 水印 
struct node{
	int num1,num2;
	int x;
}arr[500100];
int tree[500100];
int n;

bool cmp(node a,node b)
{
	return a.x<b.x;
}

bool cmp1(node a,node b)
{
	return a.num1<b.num1;
}

int lowbit(int i)
{
	return i&(-i);
}

void updata(int i)
{
	while(i<=n)
	{
		tree[i]++;
		i=i+lowbit(i);
	}
}

ll Query(int i)
{
	ll res=0;
	while(i>0)
	{
		res=res+tree[i];
		i=i-lowbit(i);
	}
	return res;
}

int main()
{
	while(cin>>n&&n!=0)
	{
		clean(arr,0);
		clean(tree,0);
		for(int i=1;i<=n;++i)
		{
			cin>>arr[i].x;
			arr[i].num1=i;
		}
		sort(arr+1,arr+n+1,cmp);//按照x从小到大 
		for(int i=1;i<=n;++i)
			arr[i].num2=i;//离散化 
		sort(arr+1,arr+1+n,cmp1);//回归原来的顺序
		//此时,num2即为离散后的顺序 
		ll ans=0;
		for(int i=1;i<=n;++i)//找逆序数 
		{
			updata(arr[i].num2);
			ans=ans+i-Query(arr[i].num2);
		}
		cout<<ans<<endl;
	}
}

猜你喜欢

转载自blog.csdn.net/qq_40482358/article/details/81252440