题意:
给定长度为n的数组a,可以进行两种操作:
1.删除数组中的一个数,代价为c。
2.在数组中任意位置插入一个数,代价为d。
求把a变成一个全排列的最小代价。
分析:
首先对数组去重,去重部分是一定要付出的代价,以最优策略选择,可以对数组进行排序并且枚举数组元素,以每一个数组元素作为全排列长度,如果a[i]-i!=0说明前面缺少某些元素,那么就需要付出代价c*(a[i]-i),对于后面的数,一定都大于当前的a[i],因此将后面的数全部删除,代价为d*(m-i)。所以枚举的每一个数的代价为c*(a[i]-i)+d*(m-i)。对所有代价取最小值再加上之前去重的代价即可得到最小的代价。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=3e5+10;
ll f[N];
void solve()
{
int t;
cin>>t;
while(t--)
{
int n;
ll c,d;
cin>>n>>c>>d;
set<ll> a;
for(int i=0;i<n;i++)
{
ll x;
cin>>x;
a.insert(x);
}
int cnt=0;
ll ans=(ll)(n-a.size())*c;
for(auto x:a) f[++cnt]=x;
ll res=2e18;
for(int i=1;i<=cnt;i++)
{
res=min(res,(ll)(f[i]-i)*d+(ll)(cnt-i)*c);
}
res=min(res,(ll)cnt*c+d);
cout<<ans+res<<'\n';
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
solve();
return 0;
}