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

题目大体意思就是说给定一组数据,求把这组数据排列成有序数组的交换次数,除了可以用数据结构里面提到的归并排序,也可以用线段树,但是在用线段树的时候有一点一定要注意,就是数据必须要离散化,题目里给出了这样两个限制,输入的数据量小于500000,每个数据小于999999999,也就是说,如果不进行离散化,构建线段树的时候就需要999999999<<2个节点,远超出程序的内存限制,所以只能进行离散化,将节点数缩小到500000<<2的范围内,这样就可以使程序在合理范围内。

离散化大体过程:先将数据和编号存在一个结构体数组中,对这个数组进行sort排序,排序后把名次对应存在另外一个数组里,这样就能够实现将过长数据转化为离散数据的过程,在线段树查询的时候直接使用名次来代替原始数据。

AC代码

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<memory.h>
using namespace std;
struct Node {
	int l,r,num;
};
struct Num{
	int id,num;
};
struct Num N[500005];
struct Node node[500005<<2];
int b[500005];
void build(int x,int y,int m)
{
	node[m].l=x;
	node[m].r=y;
	node[m].num=0;
	if(x==y) return;
	int mid=(x+y)/2;
	build(x,mid,m<<1);
	build(mid+1,y,m<<1|1);
	node[m].num=node[m<<1].num+node[m<<1|1].num;
}
void update(int tar,int m)
{
	if(node[m].l==tar&&node[m].r==tar) 
	{
		node[m].num++;
		return;
	}
	int mid=(node[m].l+node[m].r)/2;
	if(tar<=mid) update(tar,m<<1);
	else update(tar,m<<1|1);
	node[m].num=node[m<<1].num+node[m<<1|1].num;
}
int query(int x,int y,int m)
{
	if(node[m].l==x&&node[m].r==y)
		return node[m].num;
	int mid=(node[m].l+node[m].r)/2;
	if(y<=mid) 
		return query(x,y,m<<1);
	else if(x>mid) 
		return query(x,y,m<<1|1);
	else 
		return query(x,mid,m<<1)+query(mid+1,y,m<<1|1); 
}
bool cmp(struct Num x,struct Num y)
{
	return x.num<y.num;
}
int main()
{
	int n;
	while(scanf("%d",&n)&&n)
	{
		build(0,n+1,1);
		memset(b,0,sizeof(b));
		long long int ans=0;
		for(int i=0;i<n;i++)
		{
			cin>>N[i].num;
			N[i].id=i;
		}
		sort(N,N+n,cmp);
		for(int i=0;i<n;i++)
			b[N[i].id]=i+1;
		for(int i=0;i<n;i++)
		{
			ans+=query(b[i]+1,n+1,1);
			update(b[i],1);
		}
		cout<<ans<<endl;	
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43849505/article/details/87187489