Codeforces 1328F Make k Equal

如果一个数组中已经有一种数 $\ge k$ 个了,那么答案一定是 $0$。

否则的话,显然我们最终要凑的数字一定是数组当中的一个数。

所以我们就可以枚举这个数。

数组先排个序,分三种情况,一种是只动左边,一种是只动右边,还有一种是两边都动。

如果只动前面,把 $a_1 \sim a_i$ 全部弄成 $a_i$ 需要多少步?

答案是 $i \cdot a_i- \sum\limits_{j=1}^{i}a_j$。

但是这样就一共有了 $i$ 个 $a_i$。如果 $i = k$,那么正好;如果 $i < k$,那么是不符合条件的;如果 $i > k$,可以发现,我们又浪费了一部分,即多了 $i - k$ 个,那么怎么办呢?很简单,让这 $i - k$ 个保持在 $a_{i} - 1$ 就好了,所以用:

$$i \cdot a_i- \left(\sum_{j=1}^{i}a_j\right) - (i - k)$$

来更新答案。

只动后面同理,条件是 $n - i + 1 \ge k$,用:

$$\left(\sum_{j=i}^{n}a_j \right)- (n - i + 1) \cdot a_i - \left((n - i + 1) - k\right)$$

来更新答案。

如果同时 $i<k$ 且 $n-i+1<k$,那么两边就都要动了,这时相等的数的个数恰好为 $n$,很显然,把上面两个式子拼起来即可,用:

$$i \cdot a_i- \left(\sum_{j=1}^{i}a_j\right) +\left(\sum_{j=i}^{n}a_j \right)- (n - i + 1) \cdot a_i - (n-k)$$

来更新答案。

$\sum\limits_{j=1}^{i}a_j$ 和 $\sum\limits_{j=i}^{n}a_j$ 可以预处理,所以时间复杂度是 $\mathcal O(n)$。

代码供参考。

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e5 + 5;
int n, k, a[N], pre[N], suf[N], ans = LLONG_MAX, cnt[N];
signed main()
{
    cin >> n >> k;
    for(int i = 1; i <= n; i++) cin >> a[i];
    sort(a + 1, a + n + 1);
    for(int i = 1; i <= n; i++) pre[i] = pre[i - 1] + a[i];
    for(int i = n; i >= 1; i--) suf[i] = suf[i + 1] + a[i];
    for(int i = 1; i <= n; i++)
    {
        if(a[i] == a[i - 1]) cnt[i] = cnt[i - 1] + 1;
        else cnt[i] = 1;
        if(cnt[i] >= k) return puts("0") && 0;
    }
    for(int i = 1; i <= n; i++)
    {
        if(i >= k) ans = min(ans, i * a[i] - pre[i] - (i - k));
        if(n - i + 1 >= k) ans = min(ans, suf[i] - (n - i + 1) * a[i] - (n - i + 1 - k));
        ans = min(ans, i * a[i] - pre[i] + suf[i] - (n - i + 1) * a[i] - (n - k));
    }
    cout << ans << endl;
    return 0;
}

原文地址:https://www.cnblogs.com/syksykCCC/p/CF1328F.html

时间: 2024-10-16 17:07:28

Codeforces 1328F Make k Equal的相关文章

CF-1328 F. Make k Equal

F. Make k Equal 题目链接 题意 长度为n的序列,每次可以选择一个最大的数字将其减一或者选择一个最小的数字将其加一,问最少操作多少次可以使得序列中至少存在 k 个一样的数字 分析 官方题解:http://codeforces.com/blog/entry/75246 可以想到最后一样的数字,一定是在原序列里面出现的,所以将原数组离散化之后,枚举最后一样的数字,并努力把它凑够 k 个.如何凑?借助左侧或者右侧的数字.只要借助了某侧的数字,那么这一侧全部的数字都要先挪动它旁边的那个位置

Make k Equal from Codeforces Round #629 (Div. 3)

description you are given an array and you are asked to make \(k\) elements of it equal after some operations. you can make one of the following operations: take one of the minimum and increase its value by \(1\) take one of the maximum and subtract

Codeforces Round #629 (Div. 3) F - Make k Equal (离散化 树状数组维护前缀和)

https://codeforces.com/contest/1328/problem/F 首先把a数组处理成pair对(num,cnt),表示数字num有cnt个,然后按num升序排序离散化一下. 对于一个数x,若想使得小于x的数字都变成x,必须先把所有小于x的数变成x-1,然后再+1变成x. 同理,要使得大于x的数变成x,必须把所有大于x的数字变成x+1,然后再-1变成x. 以上是题意所要求的必须操作. 思路: 1. 用f[i]数组记录离散化后前i大的数字的总数,那么对于任意第i大数字,可以

Codeforces Gym 100187K K. Perpetuum Mobile 构造

K. Perpetuum Mobile Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100187/problem/K Description The world famous scientist Innokentiy almost finished the creation of perpetuum mobile. Its main part is the energy generator whic

698. Partition to K Equal Sum Subsets

问题描述: Given an array of integers nums and a positive integer k, find whether it's possible to divide this array into k non-empty subsets whose sums are all equal. Example 1: Input: nums = [4, 3, 2, 3, 5, 2, 1], k = 4 Output: True Explanation: It's po

[Swift]LeetCode698. 划分为k个相等的子集 | Partition to K Equal Sum Subsets

Given an array of integers nums and a positive integer k, find whether it's possible to divide this array into k non-empty subsets whose sums are all equal. Example 1: Input: nums = [4, 3, 2, 3, 5, 2, 1], k = 4 Output: True Explanation: It's possible

Partition to K Equal Sum Subsets

Given an array of integers nums and a positive integer k, find whether it's possible to divide this array into k non-empty subsets whose sums are all equal. Example 1: Input: nums = [4, 3, 2, 3, 5, 2, 1], k = 4 Output: True Explanation: It's possible

codeforces gym 100357 K (表达式 模拟)

题目大意 将一个含有+,-,^,()的表达式按照运算顺序转换成树状的形式. 解题分析 用递归的方式来处理表达式,首先直接去掉两边的括号(如果不止一对全部去光),然后找出不在括号内且优先级最低的符号.如果优先级相同,则如果是左结合性(+,-,*,/)则选择最右边的一个,如果是右结合性(^)则选择最最左边的一个. 主要恶心的地方在于输出上.主要是记录一下每个点和符号的位置,在递归和返回时传递一些参数. ps:虽然输出比较恶心,但最终实现出来后还是感到十分地身心愉悦. 参考程序 1 #include

Codeforces 1065C Make It Equal (差分+贪心)

题意:n个塔,第i个塔由$h_i$个cube组成,每次可以切去某高度h以上的最多k个cube,问你最少切多少次,可以让所有塔高度相等 k>=n, n<=2e5 思路:差分统计每个高度i有的方块数nh[i],然后从高到低贪心的切就行了 代码: #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include