zoukankan      html  css  js  c++  java
  • CF1328F-Make k equal (补)(二分)

    题目链接:

    https://codeforces.com/contest/1328/problem/F

    思路:

    题目大意是你可以进行两种操作,一种是将最大数减1,另一种是将最小数加1,问你最少经过多少次操作,能使序列中存在k个相同的数

    我们先将数组进行排序,然后用前缀和对数组进行预处理。

    假设我们以a[i]这个数为标准,通过二分找到第一个大于a[i]的位置index,对于大于a[i]的数来说,我们首先通过操作将

    a[index]-a[n]中的所有数变成a[i]+1,那么这一过程中消耗的操作数为(sum[n]-sum[index-1])-(n-index+1)*(x+1),

    若原数组中有num个a[i]这样的数,那么我们接下来要消耗的操作数为min(k-num,n-index+1),如果此时a[i]的个数仍然

    小于K,我们再考虑对小于a[i]的数进行操作,这里不再赘述,由于先找小的可能比先找大的更优,所以我又分情况讨论了,

    代码很复杂,但看别人的代码好像很简单

    代码:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int MAXN=2e5+5;
     5 const ll INF=3e18;
     6 ll a[MAXN],n,k,sum[MAXN];
     7 ll ans=INF;
     8 map<int,int>m;
     9 ll check1(int x)
    10 {
    11     ll res=0;ll index;ll num=m[x];
    12     index=upper_bound(a+1,a+1+n,x)-a;
    13     res+=(sum[n]-sum[index-1])-(n-index+1)*(x+1);
    14     res+=min(k-num,n-index+1),num+=min(k-num,n-index+1);
    15     if(num<k)
    16     {
    17         index=lower_bound(a+1,a+1+n,x)-a-1;//cout<<index<<" "<<num<<" "<<endl;
    18         res+=index*(x-1)-sum[index];
    19         res+=k-num;
    20     }
    21     return res;
    22 }
    23 ll check2(int x)
    24 {
    25     ll res=0;ll index;ll num=m[x];
    26     index=lower_bound(a+1,a+1+n,x)-a-1;
    27     res+=index*(x-1)-sum[index];
    28     res+=min(k-num,index),num+=min(k-num,index);
    29     if(num<k)
    30     {
    31         index=upper_bound(a+1,a+1+n,x)-a;//cout<<index<<" "<<num<<" "<<endl;
    32         res+=(sum[n]-sum[index-1])-(n-index+1)*(x+1);
    33         res+=k-num;
    34     }
    35     return res;
    36 }
    37 int main()
    38 {
    39     ios::sync_with_stdio(false);
    40     cin.tie(0);
    41     cin>>n>>k;
    42     for(int i=1;i<=n;i++)
    43     {
    44         cin>>a[i];m[a[i]]++;
    45         if(m[a[i]]>=k)
    46         {
    47             cout<<"0"<<endl;
    48             return 0;
    49         }
    50     }
    51     sort(a+1,a+1+n);
    52     for(int i=1;i<=n;i++)
    53         sum[i]=sum[i-1]+a[i];
    54     for(int i=1;i<=n;i++)
    55         ans=min(ans,min(check1(a[i]),check2(a[i])));
    56     cout<<ans<<endl;
    57     return 0;
    58 }
  • 相关阅读:
    基本类型数组与包装类型数组相互转换
    (转载)JVM中的内存模型与垃圾回收
    Python之threading多线程
    Python之基于socket和select模块实现IO多路复用
    Python之利用socketserver实现并发
    Python的网络编程socket模块
    Python设计模式之一(单例模式)
    Python异常处理
    Python面向对象之常用的特殊方法(5)
    Python面向对象之私有方法(4)
  • 原文地址:https://www.cnblogs.com/ljxdtc666/p/12584455.html
Copyright © 2011-2022 走看看