AT2645题解

· · 题解

题目传送门

做法

本题有 hall 定理 + 线段树做法,详见大佬的博客

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

实现:

思路来自大佬 @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(); }