题意大概就是有n个数字,要使至少有k个相同,可以花费b使一个数+5,可以花费c使一个数+1,求最小花费。
要对齐的数肯定是在[v,v+4]之间,所以分别枚举模为0~4的情况就可以了。
排序一下,然后化绝对为相对
例如有 3 6 8 14这4个数,模4,
耗费分别为c+2b 3c+b c+b 0
可以-2b(移动到14时=2*5+4,倍率2)变成c 3c-b c-b -2b
就是说每次都取倍率然后减其花费压入优先队列,若元素数量大于k就弹出最大的那个就可以了
/*没时间自己写个就把其他人的题解搞来了。。。*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <set>
#include <map>
#include <stack>
#include <vector>
#include <string>
#include <queue>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <ctime>
using namespace std;
typedef pair<int, int> pii;
typedef long long ull;
typedef long long ll;
typedef vector<int> vi;
#define xx first
#define yy second
#define rep(i, a, n) for (int i = a; i < n; i++)
#define sa(n) scanf("%d", &(n))
#define vep(c) for(decltype((c).begin()) it = (c).begin(); it != (c).end(); it++)
const int mod = int(1e9) + , INF = 0x3fffffff, maxn = 1e5 + ; //ll que[maxn * 4];
int ct[maxn * ]; //小根堆仿函数
class cmp
{
public:
bool operator()(const ll a, const ll b) {
return a > b;
}
}; int main(void) {
#ifdef LOCAL
freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
#endif
int n, k, b, c;
while (cin >> n >> k >> b >> c) {
rep (i, , n) sa(ct[i]), ct[i] += 1e9;
sort(ct, ct + n);
ll ans = 1ll << ;
if (c * <= b) {
ll sum = ;
for (int i = ; i < n; i++) {
sum += ct[i];
if (i >= k - ) {
ans = min(ans, ((ll)ct[i] * k - sum) * c);
sum -= ct[i - k + ];
}
}
} else {
rep (md, , ) {
ll sum = ;
//int head = 0, tail = 0;
priority_queue<ll, vector<ll>, cmp> que;
rep (i, , n) {
ll cc = (md + - ct[i] % ) % ;
ll bb = (ct[i] + cc) / ;
//等效处理之后的值.
ll cost = bb * b - cc * c;
sum += cost;
// while (head == tail || que[tail - 1] > cost) que[tail++] = cost;
que.push(cost); if (i >= k - ) {
ans = min(ans, (bb * k * b - sum));
sum -= que.top();
que.pop();
}
}
}
}
cout << ans << endl;
} return ;
}
o(n)的解法?没有啦