abc271_c Manga 题解

Manga

题意

有一部连载漫画,共 \(10^9\) 卷,你手上有 \(n\) 卷漫画,第 \(i\) 卷是连载中的第 \(a_i\) 卷。

你在看漫画之前,可以执行以下操作若干次(可以不执行):

  • 若手上还有至少两卷漫画,可以卖掉任意两卷,并买一卷任意卷数的漫画。

你不想看不连续的漫画,所以你只能从连载第一卷开始读,直到你手上没有连载的下一卷,问你最多可以读多少卷。

数据范围

  • \(1 \leqslant n \leqslant 3 \times 10^5\)
  • \(1 \leqslant a_i \leqslant 10^9\)

思路

首先,我们手上会有重复卷数的漫画,这些废卷可以直接卖掉。

然后就是一个双指针,当手上没有废卷而且还有空缺时,我们可以拿手上卷数最大的漫画(排序)去补空缺,有些细节,总体难度不大。

当然你也可以二分,二分最多能阅读几卷,check函数详见代码。

复杂度

  • 时间:\(O(n \log n)\)
  • 空间:\(O(n)\)

Code

排序双指针代码
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 3e5 + 10;

int n, m, a[N], b[N], ans, now = 1, sum;

int main () {
  ios::sync_with_stdio(0), cin.tie(0);
  cin >> m;
  for (int i = 1; i <= m; i++) {
    cin >> b[i];
  }
  sort(b + 1, b + m + 1);
  for (int i = 1; i <= m; i++) {
    if (b[i] == b[i - 1]) { // 废卷
      sum++; // 统计废卷卷数
    } else {
      a[++n] = b[i];
    }
  }
  for (int i = 1, j = n; i <= j; ) {
    if (a[i] != now) { // 现在考虑的这本不能接上上一卷
      if (sum >= 2) { // 优先使用废卷
        sum -= 2;
      } else if (sum) { // 废卷还剩一本,用掉废卷和最后的一卷
        j--, sum = 0;
      } else if (j - i >= 1) { // 还有可以卖掉的
        j -= 2; // 卖掉最大的两卷
      } else {
        break; // 退出
      }
    } else {
      i++;
    }
    ans++, now++;
  }
  cout << ans + sum / 2; // 可能还有废卷,也要卖掉
  return 0;
}
二分代码
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 3e5 + 10;

int n, m, a[N], b[N], ans, now = 1, sum, l, r;

bool check (int x) {
  int num = sum, cnt = x; // num 统计可以卖掉的卷数,cnt 统计空缺数
  for (int i = 1; i <= n; i++) {
    if (a[i] <= x) { // 在前 x 卷中
      cnt--; // 空缺数减 1
    } else {
      num++; // 卖掉它
    }
  }
  return (cnt * 2 <= num);
}

int main () {
  ios::sync_with_stdio(0), cin.tie(0);
  cin >> m;
  r = m;
  for (int i = 1; i <= m; i++) {
    cin >> b[i];
  }
  sort(b + 1, b + m + 1);
  for (int i = 1; i <= m; i++) {
    if (b[i] == b[i - 1]) { // 废卷
      sum++; // 统计废卷卷数
    } else {
      a[++n] = b[i];
    }
  }
  while (l < r) {
    int mid = (l + r + 1) >> 1;
    if (check(mid)) {
      l = mid;
    } else {
      r = mid - 1;
    }
  }
  cout << l;
  return 0;
}
posted @ 2023-05-22 11:53  wnsyou  阅读(65)  评论(0编辑  收藏  举报