AT2645 [ARC076D] Exhausted?题解

题目传送门

题目描述

\(m\) 个椅子在数轴上排列,第 \(i\) 张椅子的坐标为 \(i\)

高桥君和他的朋友一共有 \(n\) 个人。高桥君他们因为玩了太久的游戏,大家的腰和背都很痛,所以他们很有必要坐在椅子上休息一下。

高桥君他们每个人坐的椅子的坐标都很讲究,第 \(i\) 个人想坐在坐标不大于 \(l_i\) 的椅子上,或者坐在坐标不小于 \(r_i\) 的椅子上。当然,一个的椅子只能坐一个人。

可这样计算下去,可能会让他们不能都坐在椅子上休息。青木君关心高桥君他们的健康,尽可能多地增加椅子,让高桥君他们都能够坐在椅子上休息。 椅子可以添加到任意的实数坐标上,请求出需要添加椅子数量的最小值。

输入格式

第一行输入两个数 \(n\)\(m\)

接下来的第二行到 \(n+1\) 行依次输入 \(l_i\)\(r_i\)

输出格式

输出需要添加的椅子数量的最小值。

样例一

input

7 6
0 7
1 5
3 6
2 7
1 6
2 6
3 7

output

2

样例解释

\(4\) 个人依次坐在坐标为 \(3,2,1,4\) 的椅子上,所以椅子不需要添加。

样例二

input

3 1
1 2
1 2
1 2

output

2

样例解释

如果将椅子添加到坐标 \(0\)\(7\),则可以将 \(7\) 人按顺序放在坐标 \(0,5,3,2,6,1,7\) 中。

做法

本题有 hall 定理做法,详见大佬的博客,这里主要讲解贪心。

思路:让所有的人先尽可能坐在左面,坐不下的做右面,然后实在坐不了的就填椅子。

实现:

  • \(ex_i\) 数组:果为 -1 即表示 \(i\) 这个位置的椅子是空的,0 表示坐了人,其余数字均表示\(ex_i\) 个人还没有坐在椅子上,他们不可以坐在坐标小于 \(i\) 的椅子上
  • 把所有人按照以 \(l\) 为第一关键字,\(r\) 为第二关键字排序,\(ex\) 数组初值均为 -1,每次选择一个人,看他前面能坐的椅子是否坐满,如果没满,就直接做当前所剩椅子中最左面的一个,并插入到优先队列中表示可以被替换,如果已经满了,就要从所有可以被替换的这些人里找第二关键字最小的一个替换(这样可以给后面留足够大的空间让更多人坐),这样的话自己就坐在了。
  • 统计答案:考虑 \(ex_i\) 数组后缀和的含义即为从 \(i\)\(n\) 有多少个人没有椅子,且这些人一定要坐在坐标大于等于 \(i\) 的位置,这样后缀和中最大的即为答案。

思路来自大佬 @tjn1234

代码

#include <bits/stdc++.h>
using namespace std;
namespace Std {
int n, m, now, ex[200010], ans, res;
struct node {
  int l, r;
  friend bool operator<(const node& a, const node& b) {
    return (a.l == b.l) ? a.r < b.r : a.l < b.l;
  }
} t[200010];
struct num {
  int sum;
  friend bool operator<(const num& a, const num& b) { return a.sum > b.sum; }
};
priority_queue<num> q;
int main() {
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= n; i++) {
    scanf("%d%d", &t[i].l, &t[i].r);
  }
  sort(t + 1, t + n + 1);
  for (int i = 1; i <= m; i++) ex[i] = -1;
  for (int i = 1; i <= n; i++) {
    if (t[i].l == 0) {
      ex[t[i].r]++;
    } else if (t[i].l == now) {
      num u = q.top();
      q.pop();
      ex[u.sum]++;
      u.sum = t[i].r;
      q.push(u);
    } else {
      ex[++now]++;
      num u;
      u.sum = t[i].r;
      q.push(u);
    }
  }
  for (int i = m + 1; i >= 0; i--) {
    res += ex[i];
    ans = max(ans, res);
  }
  printf("%d\n", ans);
  return 0;
}
}  // namespace Std
int main() { return Std::main(); }
posted @ 2022-05-21 23:29  Wilson_Inversion  阅读(26)  评论(0编辑  收藏  举报