Description
给出一个长度为 n n 的序列,该序列一个逆序对代价为 x x ,交换相邻两元素代价为,问该序列的最小代价
Input
多组用例,每组用例首先输入三个整数 n,x,y n , x , y ,之后输入 n n 个整数
(1≤n,x,y≤105,−109≤ai≤109) ( 1 ≤ n , x , y ≤ 10 5 , − 10 9 ≤ a i ≤ 10 9 )
Output
输出该序列的最小代价
Sample Input
3 233 666
1 2 3
3 1 666
3 2 1
Sample Output
0
3
Solution
交换相邻两个位置至多可以消除一个逆序对,只要该序列还存在逆序对则必然可以找到一对相邻位置使得交换这两个位置可以消除一个逆序对,也即逆序对数为交换相邻两个位置的值来排序的最少次数,故答案即为逆序对数乘上 min(x,y) m i n ( x , y )
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 100005
typedef long long ll;
struct node
{
int val,pos;
}a[maxn];
int b[maxn];
int n,x,y;
int cmp(node a,node b)
{
if(a.val!=b.val)
return a.val<b.val;
return a.pos<b.pos;
}
int getsum(int x)
{
int sum=0;
while(x>0)
{
sum+=b[x];
x-=x&-x;
}
return sum;
}
void update(int x,int v)
{
while(x<=maxn)
{
b[x]+=v;
x+=x&-x;
}
}
int main()
{
while(~scanf("%d%d%d",&n,&x,&y))
{
memset(b,0,sizeof(b));
for(int i=0;i<n;i++)
{
scanf("%d",&a[i].val);
a[i].pos=i+1;
}
sort(a,a+n,cmp);
ll ans=0;
for(int i=n-1;i>=0;i--)
{
ans+=getsum(a[i].pos);
update(a[i].pos,1);
}
printf("%I64d\n",ans*min(x,y));
}
return 0;
}