逆序数 Ultra-QuickSort

本文介绍了一种高效算法来计算特定排序算法Ultra-QuickSort处理输入序列时所需的交换次数,即计算序列的逆序数。通过采用分治策略,避免了O(n^2)的时间复杂度,确保了在大数据集上的效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考链接:https://blog.youkuaiyun.com/wan1314mum/article/details/42561127

题目链接:https://vjudge.net/contest/243680#problem/F

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

根据题意,其实就是求逆序数;

思考:若是直接暴力扫描,复杂度为O(n^2),假如数据过大,会TLE,所以考虑用分治的思想,将区间一分为二考虑,那么
总区间的逆序数就为分开后的左区间里的逆序数,右区间里的逆序数和左右区间比较产生的逆序数三者之和,在左右区
间里的逆序数可以递归求得(顺便将区间排好序),而对于逆序数分别由左区间和右区间构成的数构成,我们则枚举右区
间的数,统计左区间比他大的数字,累加起来就好了。

 

#include<iostream>
#include<cstring>
using namespace std;

int vec[500050];
int temp[500050];

long long  ans=0;//计数尽量用long long 好几次就因为int 错了; 

void slove(int left,int mid,int right){
	int i=left;
	int j=mid;;
	int n=mid+1;
	int m=right;
	int k=0;
	while(i<=j && n<=m){
		if(vec[i]>vec[n]){
			ans+=mid-i+1;//记录左区间的数字有多少大于右边的数字; 
			temp[k++]=vec[n++];
		}
		else{
			
			temp[k++]=vec[i++];
		}
	}
	while(i<=j){
		temp[k++]=vec[i++];
	}
	while(n<=m){
		temp[k++]=vec[n++];
	}
	for(int i=0;i<k;i++){
		vec[left+i]=temp[i];
	}
}


void msort(int left,int right){
	if(left<right){
		int mid=(left+right)/2;
		msort(left,mid);
		msort(mid+1,right);
		slove(left,mid,right);
	} 
}




int main(){
	int n;
	while(cin>>n,n){ 
	ans=0;
	memset(vec,0,sizeof(vec));
	memset(temp,0,sizeof(temp));
	for(int i=0;i<n;i++){
		cin>>vec[i];
	}
	msort(0,n-1);
//	for(int i=0;i<n;i++){
//		cout<<vec[i]<<" ";
//	}
	cout<<ans<<endl;
}
	
	return 0;
} 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值