Codeforces Round #592 (Div. 2)E. Minimizing Difference(二分)

题目来源:

https://codeforces.com/problemset/problem/1244/E

題目描述:

在这里插入图片描述

题意:

给定一个长度为 n n 的序列和一个操作次数 k k ,现在你可以给任意一个数加一或者减一,问不超过 k k 次能取得的最小极差是多少。

思路:

因为是问的极差,所以肯定是对当前的最大值和最小值进行改变最优,所以问题具有单调性,二分极值是否满足 k k 次即可,预处理前缀和。

参考代码:

/* CF was purple years ago!
 * Thanks cf-tool!
 * Author: nuoyanli
 * Time: 2019-11-15 09:35:09
 **/

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define lson l, mid, root << 1
#define rson mid + 1, r, root << 1 | 1
#define min(a, b) a > b ? b : a
#define max(a, b) a < b ? b : a
#define ll long long
using namespace std;
const int N = 1e5 + 10;
const int M = 25;
struct node {
  ll x, y;
  bool operator<(const node &_a) const { return y < _a.y; }
};
ll n, k, a[N], sum[N];
bool check(int x) {
  ll ans = 1e18, r = 1, l = 1;
  for (int i = 1; i <= n; i++) {
    while (r < n && a[r + 1] - a[i] <= x)
      r++;
    ans = min(ans, a[i] * i - sum[i] + sum[n] - sum[r] - (a[i] + x) * (n - r));
  }
  for (int i = 1; i <= n; i++) {
    while (a[i] - a[l] > x)
      l++;
    ans = min(ans, sum[n] - sum[i] - a[i] * (n - i) + (a[i] - x) * (l - 1) - sum[l - 1]);
  }
  return ans <= k;
}
signed main() {
  // printf("%lld\n", inf);
  scanf("%lld%lld", &n, &k);
  for (int i = 1; i <= n; i++)
    scanf("%lld", &a[i]);
  sort(a + 1, a + 1 + n);
  for (int i = 1; i <= n; i++)
    sum[i] = sum[i - 1] + a[i];
  int l = 0, r = a[n] - a[1] + 1;
  while (l <= r) {
    int mid = (l + r) >> 1;
    if (check(mid))
      r = mid - 1;
    else
      l = mid + 1;
  }
  return !printf("%d\n", l);
  return 0;
}
发布了293 篇原创文章 · 获赞 212 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/nuoyanli/article/details/103083955