题意:给定一个整数序列,如果交换两个相邻数,花费y元,每消除一个逆序数需花费x元,其实x,y等效,学完线代就知道,每次交换两个相邻的数,逆序数必定改变,而我们必定向着逆序数减小的方向进行,所以我们每次花费x或者y元都可以使逆序数减小1,这样问题就转化为求序列的逆序数,最后结果乘上min(x, y)即可。
问题就在于序列中的数太大了,树状数组存不下,需要离散化一下
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<cmath>
using namespace std;
int n, x, y;
struct node
{
int cnt;
long long num;
}a[100005];
long long c[100005];
int lowbit(int x)
{
return x & (-x);
}
void update(int x)
{
while(x <= 100005)
{
c[x] += 1;
x += lowbit(x);
}
}
int getsum(int x)
{
int ans = 0;
while(x > 0)
{
ans += c[x];
x -= lowbit(x);
}
return ans;
}
bool cmp(node a, node b)
{
if(a.num != b.num) return a.num < b.num;
else return a.cnt < b.cnt;
}
int main()
{
while(scanf("%d%d%d",&n,&x,&y) != EOF)
{
int cnt1 = 0;
memset(c, 0, sizeof(c));
for(int i = 1; i <= n; i ++)
{
scanf("%lld",&a[i].num);
a[i].cnt = ++ cnt1;
}
sort(a + 1, a + 1 + n, cmp);
long long ans = 0;
for(int i = 1; i <= n; i ++)
{
update(a[i].cnt);
ans += (i - getsum(a[i].cnt));
}
printf("%lld\n", ans * min(x, y));
}
return 0;
}