题目连接: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);
}
}