告诫后人,不要写这种假做法
查看原帖
告诫后人,不要写这种假做法
52243
RenaMoe楼主2021/4/20 14:30

当你没看题解之前,可能想随手写了一个贪心试试,比如像这样:

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';
}

就是首先一个人能先尝试坐左边再坐右边,那么按照 lil_i 从小到大排序,从左向右贪心的给每个座位分配人,没有安排上的拎出来。剩下这些人那就按照类似的方式按 rir_i 从大到小排序,从右向左贪心的给每个座位分配人。

这个在 AtCoder 上过了,但是这是的!在校内模拟赛被 hack 没了。

这个做法的问题在于,当出现了在左侧安排不上座位的人时,需要拎出来的不一定是这个人,而是应该挑选一个 rir_i 最小的人替换他最优。

2021/4/20 14:30
加载中...