2.1 杰哥和序列

算法设计与分析 2.1 杰哥和序列

题目描述

杰哥喜欢单调不下降的序列,因为他觉得这样的序列有美感。

今天杰哥得到了一个长度为的序列,但是他今天心情不好,他把序列丢给了你,要你把他变成单调不下降的序列。

你可以花费A单位的时间交换序列中两个相邻的元素,当然,你也可以选择干一半摸鱼罢工。

最后你要把序列还给杰哥,但是如果杰哥发现序列中每有一个逆序对,就会把你抓过去,训话B单位时间。

你想花最少的时间(主动交换元素+被动被杰哥训话的时间)把这个事解决了,问这个时间是多少。

逆序对的定义:存在两个整数 D[i] 和 D[j] ,满足 i < j ,且 D[i] > D[j],则 < D[i] , D[j] > 这个有序对称为 D 的一个逆序对。

输入格式

输入第一行为三个空格隔开的正整数 N、A、B,代表序列长度为N,A和B的含义见题面。

接下来一行有 N 个整数,第i个数表示序列的第 i 个元素 D[i]。

对于80%的数据,1 <= N, A, B <= 2000。

对于100%的数据,1 <= N, A, B <= 100000,序列元素非负且在int范围内。

输出格式

输出你要花费的最少时间。

样例输入

2 1 2
2 1

样例输出

1

参考代码

#include 
/*
求逆序对个数

归并排序中后面节点往前移动的距离总数就是逆序对的个数
 
*/

int a[100001],b[100001];
long long int count=0;

void merge(int start,int mid,int end){
	int i=start,j=mid+1,k=start;
	while(i<=mid&&j<=end)
		if(a[i]<=a[j])		// 一定要 <=
			b[k++]=a[i++];
		else{
            count+=j-k;
			b[k++]=a[j++];
			
		}
			
	while(i<=mid)
		b[k++]=a[i++];
		
	while(j<=end)
		b[k++]=a[j++];
	
	for(int i=start;i<=end;i++){
		a[i]=b[i];
	}
}

void mergeSort(int start,int end){		// end:最后一个元素的下标 
	if(start>=end) return;
	
	mergeSort(start,(start+end)/2);
	mergeSort((start+end)/2+1,end);
	merge(start,(start+end)/2,end);
}

int main(void){
	int N,A,B;
	
	std::cin>>N>>A>>B;
	
	for(int i=0;i<N;i++){
		std::cin>>a[i];
	}
	
	mergeSort(0,N-1);
	
	std::cout<<count*((A>B)?B:A);
} 

你可能感兴趣的:(算法题,算法,数据结构,c++)