zoukankan      html  css  js  c++  java
  • VK Cup 2016

    E. Bear and Contribution

    题目连接:

    http://www.codeforces.com/contest/658/problem/E

    Description

    Codeforces is a wonderful platform and one its feature shows how much someone contributes to the community. Every registered user has contribution — an integer number, not necessarily positive. There are n registered users and the i-th of them has contribution ti.

    Limak is a little polar bear and he's new into competitive programming. He doesn't even have an account in Codeforces but he is able to upvote existing blogs and comments. We assume that every registered user has infinitely many blogs and comments.

    Limak can spend b minutes to read one blog and upvote it. Author's contribution will be increased by 5.
    Limak can spend c minutes to read one comment and upvote it. Author's contribution will be increased by 1.
    Note that it's possible that Limak reads blogs faster than comments.

    Limak likes ties. He thinks it would be awesome to see a tie between at least k registered users. To make it happen he is going to spend some time on reading and upvoting. After that, there should exist an integer value x that at least k registered users have contribution exactly x.

    How much time does Limak need to achieve his goal?

    Input

    The first line contains four integers n, k, b and c (2 ≤ k ≤ n ≤ 200 000, 1 ≤ b, c ≤ 1000) — the number of registered users, the required minimum number of users with the same contribution, time needed to read and upvote a blog, and time needed to read and upvote a comment, respectively.

    The second line contains n integers t1, t2, ..., tn (|ti| ≤ 109) where ti denotes contribution of the i-th registered user.

    Output

    Print the minimum number of minutes Limak will spend to get a tie between at least k registered users.

    Sample Input

    4 3 100 30
    12 2 6 1

    Sample Output

    220

    Hint

    题意

    有n个数,你想使得其中至少k个数相同,你使得一个数加5需要花费b,使得一个数加1需要花费c

    问你最少花费多少才能满足题意。

    题解:

    首先对于整体来说,不一定是选择的是一个连续的区间的数,因为有加5这个操作

    但是我现在分开考虑,按照%5的不同的值分开考虑,每一个模数里面所选择的数一定是连续的一段

    知道这个之后,我们就暴力的去维护五个单调队列就好了。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 2e5+7;
    
    int n,k;
    long long b,c,a[maxn];
    vector<long long>v[5];
    queue<long long>Q[5];
    long long cal(long long x,long long y)
    {
        return (y-x)/5*b+(y-x)%5*c;
    }
    int main()
    {
        scanf("%d%d%lld%lld",&n,&k,&b,&c);b=min(b,5*c);
        for(int i=1;i<=n;i++)
        {
            scanf("%lld",&a[i]);
            a[i]=a[i]+1e9+1;
        }
        sort(a+1,a+1+n);
        for(int i=1;i<=n;i++)
            for(int j=0;j<5;j++)
                v[(a[i]+j)%5].push_back(a[i]+j);
        for(int i=0;i<5;i++)
        {
            sort(v[i].begin(),v[i].end());
            v[i].erase(unique(v[i].begin(),v[i].end()),v[i].end());
        }
        long long ans = 1e18;
        for(int p=0;p<5;p++)
        {
            for(int i=0;i<5;i++)while(!Q[i].empty())Q[i].pop();
            long long tmp = 0;
            int num = 0;
            for(int i=0;i<v[p].size();i++)
            {
                if(i)tmp=tmp+min(num,k)*(v[p][i]-v[p][i-1])/5*b;
                while(num<n&&a[num+1]<=v[p][i])
                {
                    num++;
                    Q[a[num]%5].push(a[num]);
                    tmp+=cal(a[num],v[p][i]);
                    if(num>k)
                    {
                        long long s = 0;
                        for(int j=0;j<5;j++)
                        {
                            if(Q[j].size())
                            {
                                int now = Q[j].front();
                                s=max(s,cal(now,v[p][i]));
                            }
                        }
                        for(int j=0;j<5;j++)
                        {
                            if(Q[j].size())
                            {
                                int now = Q[j].front();
                                if(cal(now,v[p][i])==s)
                                {
                                    Q[j].pop();
                                    tmp-=s;
                                    break;
                                }
                            }
                        }
                    }
                    if(num>=k)ans=min(ans,tmp);
                }
            }
        }
        cout<<ans<<endl;
    }
  • 相关阅读:
    List<T>直接充当Combox控件DataSource并扩展自定义记录的方法
    List转Datatable 新方法
    CDM中,实体与实体快捷方式之间的联系不能重复,否则会造成外键重复
    PD中设置外键约束名称生成规则
    查询当前数据库用户会话信息
    Word中调整编号和文字的间距
    PDM/CDM中进行搜索
    PDM后续处理-驼峰规则、清除约束、外键改名
    列举当前用户或指定用户的所有表,所有字段,以及所有约束
    PDM中列举所有含取值范围、正则表达式约束的字段
  • 原文地址:https://www.cnblogs.com/qscqesze/p/5332094.html
Copyright © 2011-2022 走看看