1 条题解
-
1
写一下 deepseek r1 给出的很容易理解的做法。
首先,我们发现豆子的纵坐标没有用。于是游戏变成:数轴上有若干个点,在数轴上放置两条线段,求最多可以覆盖多少个点。
我们用 表示第 个点的坐标,并将 数组从小到大排序。
用调整法可以证明出,两条线段不重叠时可以取到最大值。
依然用调整法,可以证明出,两条线段的左端点或右端点与某个豆子重合时,可以取到最大值。我们不妨令靠左的线段的右端点与某个豆子重合,靠右的线段的左端点与某个豆子重合。
现在我们要求出两个数组: 和 :
- 表示:左端点与 重合的线段,可以覆盖多少个豆子。
- 表示:右端点与 重合的线段,可以覆盖多少个豆子。
的求法是:找到满足 的最大的 ,则这条线段可以覆盖 内的所有点。因此 。 的值可以用二分或双指针等方法求出。
的求法类似。
我们枚举 ,表示靠左的线段的右端点与第 个豆子重合。此时靠右的线段的左端点可以与 的豆子重合,所以最优的答案即为:,维护 的后缀最大值就可以快速求出式子的值。将每个 的答案取最大值即可。
#include<bits/stdc++.h> using namespace std; #define endl '\n' const int N = 100010; int lcnt[N], rcnt[N], a[N], suf_max[N]; void solve() { int n, k; cin >> n >> k; for (int i = 1; i <= n; i++) { int y; cin >> a[i] >> y; } sort(a + 1, a + 1 + n); for (int i = 1; i <= n; i++) { int p = upper_bound(a + 1, a + 1 + n, a[i] + k) - a - 1; lcnt[i] = p - i + 1; } for (int i = 1; i <= n; i++) { int p = lower_bound(a + 1, a + 1 + n, a[i] - k) - a; rcnt[i] = i - p + 1; } suf_max[n + 1] = 0; for (int i = n; i >= 1; i--) suf_max[i] = max(suf_max[i + 1], lcnt[i]); int ans = 0; for (int i = 1; i < n; i++) ans = max(ans, rcnt[i] + suf_max[i + 1]); cout << ans << endl; } int main() { freopen("bean.in","r",stdin); freopen("bean.out","w",stdout); ios::sync_with_stdio(0); cin.tie(0);cout.tie(0); int c, T; cin >> c >> T; while (T--) solve(); return 0; }
- 1
信息
- ID
- 514
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 8
- 标签
- (无)
- 递交数
- 27
- 已通过
- 5
- 上传者