zoukankan      html  css  js  c++  java
  • Codeforces Round #629 (Div. 3) (A ~ F)

    被强♂制♂上任的第一天

    F. Make k Equal

    题目-> http://codeforces.com/contest/1328/problem/F

    题意:

    给你 n 个数 , 通过任意次操作:

    ①最大数 - 1

    ②最小数 + 1

    保证数组中有k个数相同 , 问最小操作次数

    分析:

    如果已经有k个相同的输出0,否则:

    假设最终有k个a (首先明确这里的a 一定是输入数组的其中一个值 ,这样一定可以保证最优解), 那么对于任意数b ,

    当b < a , 只有把所有小于a的数都变成a - 1 , 然后 再取其中的一个数 + 1 ,即可以得到一个a

    当b > a ,只有把所有大于a的数都变成a + 1,然后 再取其中一个数 - 1, 即可以得到一个a

    所以 , 先排序 ,接下来,枚举每个值是最优解的a , 然后a可以通过 比他小值 和 比他大的值 转移过来 , 从而求出解,详细看代码。

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn =  1e6 + 10;
    #define ll long long
    #define ios std::ios::sync_with_stdio(false)
    const ll INF(0x3f3f3f3f3f3f3f3fll);
    #define int long long
    typedef unsigned long long ULL;
    
    map<int , int>ma;
    int a[maxn];
    int b[maxn];///存不同的数
    int c[maxn];///存每个不同数的个数
    int pre[maxn] , pre_sum[maxn];///前缀个数,前缀和
    int nex[maxn] , nex_sum[maxn];///后缀个数,后缀和
    signed main()
    {
        ios;
        cin.tie(0);///
        int n , k;
        cin >> n >> k;
        int cnt = 0;
        for(int i = 1 ; i <= n ; i ++){
            cin >> a[i];
            ma[a[i]] ++;
            cnt = max(cnt , ma[a[i]]);///记录最多的数的数量
        }
        if(cnt >= k)return cout << 0 << '
    ' , 0;
    
        sort(a + 1 , a + 1 + n);
        cnt = 1;
        int sum = 1;
        for(int i = 1 ; i <= n ; i ++){
            if(a[i] == a[i + 1]) sum ++;
            else{
                b[cnt] = a[i];///记不同的数,这里用map记也可以
                c[cnt] = sum;///这个数有几个
                cnt ++ , sum = 1;
            }
        }
        n = cnt - 1;
        for(int i = 1 ; i <= n ; i ++)/// 前缀个数和前缀和
            pre[i] = pre[i - 1] + c[i] , pre_sum[i] = pre_sum[i - 1] + c[i] * b[i];
        for(int i = n ; i >= 1   ; i --) 
            nex[i] = nex[i + 1] + c[i] , nex_sum[i] = nex_sum[i + 1] + c[i] * b[i];
        int ans = INF;
        for(int i = 1 ; i <= n ; i ++){
            int now = k - c[i];///缺多少个数
            if(now > pre[i - 1]) ///如果前面的数不够的话,后面也要拿
                ans = min(ans , pre[i - 1] * (b[i] - 1) - pre_sum[i - 1] + nex_sum[i + 1] - nex[i + 1] * (b[i] + 1 ) + now);
            else ///前面的数都变成b[i] - 1 ,然后再变now个 , 
                ans = min(ans , pre[i - 1] * (b[i] - 1) - pre_sum[i - 1] + now);
            if(now > nex[i + 1]) 
                ans = min(ans , pre[i - 1] * (b[i] - 1) - pre_sum[i - 1] + nex_sum[i + 1] - nex[i + 1] * (b[i] + 1 ) + now);
            else 
                ans = min(ans , nex_sum[i + 1] - nex[i + 1] * (b[i] + 1)  + now);
        }
        cout << ans << '
    ';
        return 0;
    }
    View Code

    待补

  • 相关阅读:
    优化你的手机游戏
    vuforia 结合 unity3d 开发 AR 的 androidAPP 总结
    self._raiseerror(v) File "D:GameDevelopmentPython27libxmletreeElementTree.py", line 1506, in _raiseerror
    自定义TexturePacker插件导出自己的plist文件
    还原TexturePacker plist 文件以及图片的方法 (切开各小图片)
    no module named firefly.master.master
    c#比较器 排序
    python ——面向对象进阶(反射,双下线方法,静态方法,类方法)
    python——模块和包 需要注意的地方
    举例详解Python中的split()函数的使用方法
  • 原文地址:https://www.cnblogs.com/GoodVv/p/12594520.html
Copyright © 2011-2022 走看看