[ABC270E] Apple Baskets on Circle

[ABC270E] Apple Baskets on Circle

题意

\(n\) 个盘子,每个盘子里有 \(a_i\) 个苹果,有个人在绕盘子,每到一个盘子会吃一个苹果,问当吃到第 \(k\) 个苹果的时候,每个盘子剩下多少个苹果。

思路

二分

二分转了多少轮,但是要记录转完整后还可以多吃几个。

代码

#include <algorithm>
#include <iostream>

using namespace std;

const int MaxN = 1e5 + 10;

long long a[MaxN], n, k, cnt, l, r;

bool Check(long long x) {
  long long cnt = 0;
  for (int i = 1; i <= n; i++) {
    cnt += min(a[i], x);
  }
  for (int i = 1; i < n; i++) {
    cnt += a[i] > x;
  }
  return cnt >= k;
}

int main() {
  cin >> n >> k;
  for (int i = 1; i <= n; i++) {
    cin >> a[i], r = max(r, a[i]);
  }
  while (l < r) {
    long long mid = (l + r) >> 1;
    Check(mid) ? r = mid : l = mid + 1;
  }
  long long sum = 0;
  for (int i = 1; i <= n; i++) {
    sum += min(l, a[i]), a[i] -= min(l, a[i]);
  }
  for (int i = 1; i < n && sum < k; i++) {
    if (a[i] > 0) {
      a[i]--, sum++;
    }
  }
  for (int i = 1; i <= n; i++) {
    cout << a[i] << " ";
  }
  return 0;
}

排序

可以转满的圈数肯定是可以用一个盘子里的苹果数加上一个数得成的,所以可以排序然后找这个最大圈数,再进行处理。

代码

#include <algorithm>
#include <iostream>

using namespace std;

const int MaxN = 1e5 + 10;

long long a[MaxN], p[MaxN], n, k, sum, cnt, tmp;

int main() {
  cin >> n >> k;
  for (int i = 1; i <= n; i++) {
    cin >> a[i], p[i] = a[i];
  }
  sort(p + 1, p + n + 1);
  for (int i = 1; i <= n; i++) {
    if (sum + (p[i] - p[i - 1]) * (n - i + 1) >= k) {
      cnt += (k - sum) / (n - i + 1), tmp = (k - sum) % (n - i + 1);
      break;
    }
    sum += (p[i] - p[i - 1]) * (n - i + 1), cnt += (p[i] - p[i - 1]);
  }
  for (int i = 1; i <= n; i++) {
    a[i] = max(0ll, a[i] - cnt);
  }
  for (int i = 1; i < n && tmp >= 1; i++) {
    if (a[i] > 0) {
      a[i]--, tmp--;
    }
  }
  for (int i = 1; i <= n; i++) {
    cout << a[i] << " ";
  }
  return 0;
}

细节

这道题想到思路感觉不是很难,但败就败在了细节上,特别是处理答案和二分的过程。

posted @ 2023-05-17 21:06  yabnto  阅读(20)  评论(0编辑  收藏  举报