HDU 6318 Swaps and Inversions---贪心 2018 Multi-University Training Contest 2

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=6318

题意:有一个序列,每当有一个逆序对时,就得付钱x元,但是在结算之前。你可以交换任意两个相邻的数字,这个交换操作会花费y元。问你最后的结算时的最小花费。

题解:每次交换可以使逆序对数减一,那么我们只需要求出序列的逆序对数,然后乘上x和y的最小值即可。

卡long long

归并排序求个逆序对数即可

#include<bits/stdc++.h>
using namespace std;
const long long maxn = 1e5+7;
long long n,x,y;
long long a[maxn];
long long ans;
long long q1[maxn],head1,tail1;
long long q2[maxn],head2,tail2;
void merge(long long l,long long m,long long r){
	
	head1 = tail1 = 0;
	head2 = tail2 = 0;
	for(long long i = l; i <= m ; i ++)
		q1[tail1++] = a[i];
	for(long long i = m + 1 ; i <= r; i ++)
		q2[tail2++] = a[i];
	for(long long i = l ; i <= r ; i ++){
		if(head1 == tail1){
			a[i] = q2[head2++];
			continue;
		}
		if(head2 == tail2){
			a[i] = q1[head1++];
			continue;
		}
		if(q1[head1] > q2[head2]){
		//	cout << q1[head1] <<" "<<q2[head2] << endl; 
			ans += (tail1 - head1);
			a[i] = q2[head2++];
		//	cout << "a[i] " << a[i] << endl; 
			continue;	
		}
		else{
			a[i] = q1[head1++];
			continue;
		}
		
	}
}
void mergesort(long long l,long long r){
	if(l == r) return ;
	long long m = (l+r)/2;
	mergesort(l,m);
	mergesort(m+1,r);
	merge(l,m,r);
}
int main(){
	while(~scanf("%lld%lld%lld",&n,&x,&y)){
		ans = 0;
		for(long long i = 1 ; i <= n ; i ++){
			scanf("%lld",&a[i]);
		}
		mergesort(1,n);
	//	cout << ans << endl;
		printf("%lld\n",min(x,y)*ans);
	}
}

猜你喜欢

转载自blog.csdn.net/PK__PK/article/details/81234719