题解 P11232【[CSP-S 2024] 超速检测】
题目描述
小 D 新入职了某国的交管部门,他的第一个任务是负责国家的一条长度为
这个周末,主干道上预计出现
主干道上设置了
上司首先想知道,如果所有测速仪都是开启的,那么这
其次,为了节能,部门想关闭一部分测速仪。然而,他们不希望漏掉超速的车,也就是说,当
由于
如果你对于加速度并不熟悉,小 D 贴心地在本题的“提示”部分提供了有关加速度的公式。
对于所有测试数据,保证:
; , , ; , , ; 。
solution
速度是单调的,可以对每个车二分得到它在什么路程区间上是超速的。使用以下公式:
- 当一辆车的初速度为
、加速度 ,做匀加速运动,则当它的位移(即行驶路程)为 时,这辆车的瞬时速度为 。
为避免根号的误差,可以对两边平方。注意这个路程区间的两端只需要取到整数。
后面的部分我写了单调队列优化 dp。
code
#include <bits/stdc++.h>
using namespace std;
#ifdef LOCAL
#define debug(...) fprintf(stderr, ##__VA_ARGS__)
#else
#define debug(...) void(0)
#define endl "\n"
#endif
using LL = long long;
struct range {
int l, r;
bool operator<(const range& rhs) const { return r < rhs.r; }
};
int n, m, V, L;
LL calc(LL s, LL v0, LL a) { return v0 * v0 + 2 * a * s; }
int mian() {
cin >> n >> m >> L >> V;
LL V2 = 1ll * V * V;
vector<range> vec;
for (int i = 1; i <= n; i++) {
int d, v0, a;
cin >> d >> v0 >> a;
if (a > 0) {
if (calc(L - d, v0, a) > V2) {
int l = d, r = L, ans = L;
while (l <= r) {
int mid = (l + r) >> 1;
if (calc(mid - d, v0, a) > V2) ans = mid, r = mid - 1;
else l = mid + 1;
}
vec.push_back({.l = ans, .r = L});
}
} else if (a == 0) {
if (v0 > V) vec.push_back({.l = d, .r = L});
} else {
if (v0 > V) {
int l = d, r = L, ans = d;
while (l <= r) {
int mid = (l + r) >> 1;
if (calc(mid - d, v0, a) > V2) ans = mid, l = mid + 1;
else r = mid - 1;
}
vec.push_back({.l = d, .r = ans});
}
}
}
#ifdef LOCAL
for (auto rg : vec) debug("%d %d\n", rg.l, rg.r);
#endif
sort(vec.begin(), vec.end());
vector<int> pos(m);
for (int i = 0; i < m; i++) cin >> pos[i];
vector<int> f(m, 1e9);
auto it = vec.cbegin();
int minl = -1;
vector<int> q(m);
int l = 0, r = -1, ans1 = 0, ans2 = n;
vector<range> dec;
for (int i = 0; i < m; i++) {
while (it != vec.cend() && it->r < pos[i]) {
if (i && it->l <= pos[i - 1]) minl = max(minl, it->l), ++ans1, dec.push_back(*it);
++it;
}
while (l <= r && pos[q[l]] < minl) ++l;
if (minl == -1) f[i] = 1;
if (l <= r) f[i] = min(f[q[l]] + 1, f[i]);
while (l <= r && f[q[r]] >= f[i]) --r;
q[++r] = i;
debug("f[%d] = %d\n", i, f[i]);
}
while (it != vec.cend()) {
if (it->l <= pos.back()) minl = max(minl, it->l), ++ans1, dec.push_back(*it);
++it;
}
for (int i = 0; i < m; i++) if (pos[i] >= minl) ans2 = min(ans2, f[i]);
if (minl == -1) ans2 = 0;
cout << ans1 << " " << m - ans2 << endl;
return 0;
}
int main() {
#ifndef LOCAL
#ifdef NF
freopen("detect.in", "r", stdin);
freopen("detect.out", "w", stdout);
#endif
cin.tie(nullptr)->sync_with_stdio(false);
#endif
int t;
cin >> t;
while (t--) mian();
return 0;
}
本文来自博客园,作者:caijianhong,转载请注明原文链接:https://www.cnblogs.com/caijianhong/p/18526011/solution-P11232
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!