当你没看题解之前,可能想随手写了一个贪心试试,比如像这样:
typedef long long LL;
const int N = 2e5 + 5;
int n, m, ans;
priority_queue<int> hp;
pair<int, int> a[N];
bool vis[N];
bool cmp(pair<int, int> x, pair<int, int> y) {
if (x.first == y.first) return x.second > y.second;
return x.first < y.first;
}
inline void main() {
cin >> m >> n;
for (int i = 1; i <= m; ++i) {
int l, r;
cin >> l >> r;
a[i] = make_pair(l, r);
}
sort(a + 1, a + m + 1, cmp);
int j = 1;
for (int i = 1; i <= n; ++i) {
while (j <= m && a[j].first < i) {
hp.push(a[j].second);
++j;
}
if (j <= m) {
vis[i] = true;
++j;
}
}
while (j <= m) {
hp.push(a[j].second);
++j;
}
for (int i = n; i; --i) {
if (vis[i]) continue;
while (!hp.empty() && hp.top() > i) {
hp.pop();
++ans;
}
if (!hp.empty()) hp.pop();
else break;
}
ans += hp.size();
cout << ans << '\n';
}
就是首先一个人能先尝试坐左边再坐右边,那么按照 li 从小到大排序,从左向右贪心的给每个座位分配人,没有安排上的拎出来。剩下这些人那就按照类似的方式按 ri 从大到小排序,从右向左贪心的给每个座位分配人。
这个在 AtCoder 上过了,但是这是假的!在校内模拟赛被 hack 没了。
这个做法的问题在于,当出现了在左侧安排不上座位的人时,需要拎出来的不一定是这个人,而是应该挑选一个 ri 最小的人替换他最优。