WA两个点,求助
查看原帖
WA两个点,求助
989792
lrx___楼主2025/1/12 19:30

思路:如果 aba \ne b,则至少 400400 次后,一定有连续的 2020 个位置可以到达。最坏情况:a=19,b=20a = 19, b = 20,初始时在第 11 个,则第 381400381 \sim 400 个连续格子都可到达。

使用小根堆维护当前可以到的位置,对 liri1l_i - r_{i - 1} 的大小分类讨论,最后判断到达 nn

#include <bits/stdc++.h>
#ifndef ONLINE_JUDGE
#define debug(...) fprintf(stderr, __VA_ARGS__)
#else
#define debug(...)
#endif
using namespace std;
using namespace chrono;
typedef long long i64;

constexpr int N(2e4 + 5);
int m, a, b;
i64 n, l[N], r[N];
priority_queue<i64, vector<i64>, greater<i64>> q;

int main() {
	int i, j;
	i64 f;
	scanf("%lld%d%d%d", &n, &m, &a, &b);
	if (a == b) {
		for (i = 1; i <= m; ++i) {
			scanf("%lld%lld", l + i, r + i);
			f = l[i] / a * a + 1;
			if (f < l[i]) {
				f += a;
			}
			if (l[i] <= f && f <= r[i]) {
				puts("No");
				return 0;
			}
		}
		puts("Yes");
		return 0;
	}
	q.push(1);
	for (i = 1; i <= m; ++i) {
		scanf("%lld%lld", l + i, r + i);
		if (q.empty() || r[i] - l[i] + 1 >= b) {
			puts("No");
			return 0;
		}
		if (l[i] - r[i - 1] >= 500) {
			while (q.size()) {
				q.pop();
			}
			for (j = a; j <= b; ++j) {
				if (l[i] - 1 + j > r[i]) {
					q.push(l[i] - 1 + j);
				}
			}
		} else {
			while (true) {
				while (q.size() && l[i] <= q.top() && q.top() <= r[i]) {
					q.pop();
				}
				if (q.empty() || q.top() > r[i]) {
					break;
				}
				f = q.top();
				q.pop();
				while (q.size() && q.top() == f) {
					q.pop();
				}
				for (j = a; j <= b; ++j) {
					if (f + j < l[i] || f + j > r[i]) {
						q.push(f + j);
					}
				}
			}
		}
	}
	if (n - r[m] <= 500) {
		while (q.size() && q.top() < n) {
			f = q.top();
			q.pop();
			while (q.size() && q.top() == f) {
				q.pop();
			}
			for (j = a; j <= b; ++j) {
				if (f + j <= n) {
					q.push(f + j);
				}
			}
		}
		puts(q.size() && q.top() == n ? "Yes" : "No");
	} else {
		puts("Yes");
	}
	return 0;
}

2025/1/12 19:30
加载中...