码迷,mamicode.com
首页 > 其他好文 > 详细

codeforces VK cup 2016-round 1 D.Bear and Contribution

时间:2016-09-30 02:05:23      阅读:243      评论:0      收藏:0      [点我收藏+]

标签:

题意大概就是有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) + 7, INF = 0x3fffffff, maxn = 1e5 + 12;

//ll que[maxn * 4];
int ct[maxn * 2];

//小根堆仿函数
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, 0, n) sa(ct[i]), ct[i] += 1e9;
        sort(ct, ct + n);
        ll ans = 1ll << 60;
        if (c * 5 <= b) {
             ll sum = 0;
             for (int i = 0; i < n; i++) {
                 sum += ct[i];
                 if (i >= k - 1) {
                     ans = min(ans, ((ll)ct[i] * k - sum) * c);
                     sum -= ct[i - k + 1];
                 }
             }
        } else {
            rep (md, 0, 5) {
                ll sum = 0;
                //int head = 0, tail = 0;
                priority_queue<ll, vector<ll>, cmp> que;
                rep (i, 0, n) {
                    ll cc = (md + 5 - ct[i] % 5 ) % 5;
                    ll bb = (ct[i] + cc) / 5;
                    //等效处理之后的值.
                    ll cost = bb * b - cc * c;
                    sum += cost;
                   // while (head == tail || que[tail - 1] > cost) que[tail++] = cost;
                    que.push(cost);

                    if (i >= k - 1) {
                         ans = min(ans, (bb * k * b - sum));
                         sum -= que.top();
                         que.pop();
                    }
                }
            }
        }
        cout << ans << endl;
    }

    return 0;
}
View Code

听说还有一个o(n)的解法,待后面做

codeforces VK cup 2016-round 1 D.Bear and Contribution

标签:

原文地址:http://www.cnblogs.com/dgutfly/p/5922410.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!