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 }

 

posted @ 2020-03-27 21:22  grass_lin  阅读(290)  评论(0编辑  收藏  举报