当前位置: 首页 > article >正文

P11232 [CSP-S 2024] 超速检测(民间数据)

原题链接​​​​​​

来分析这道题,题中所说由于是匀加速直线运动,所以超速的区间一定是连续的,而且还可以被计算出来,但是要注意区间的开闭。

我们可以把超速的区间变为测速仪的分布区间。

这道题可以通过多区间贪心来实现:一条长线段上有若干条短线段(可以重复也可以不完全覆盖长线段),请在长线段上选取尽可能少的点,使得每条短线段上(含端点)都有被选取的点。

贪心实现:按照右端点排序(从小到大),然后在尽可能少的右端点初开测速仪。

代码+注释:

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 2, L = 1e6 + 2;
int t, n, m, l, V, tmp, ans1, ans2;
int d[N], v[N], a[N], p[N];
int lft[L], rgt[L]; //距离最近的测速仪编号
int ld[N], rd[N]; //每辆车超速区间的左、右端点
int g[N]; //所有超速的车的编号
int id; //后面贪心用的
bool cmp(int x, int y) {
	return rd[x] < rd[y];
}
void solve() {
	//1.常规读入+初始化
	ans1 = ans2 = 0, id = -1;
	cin >> n >> m >> l >> V;
	for (int i = 1; i <= n; ++i)
		cin >> d[i] >> v[i] >> a[i];
	for (int i = 1; i <= m; ++i) {
		cin >> p[i];
		lft[p[i]] = rgt[p[i]] = i; //这一行是2.的步骤,提前到这
	}
	//2.预处理距离最近的测速仪编号
	p[0] = 0, p[m + 1] = l + 1;
	for (int i = 0; i <= m; ++i)
		for (int j = p[i] + 1; j < p[i + 1]; ++j)
			lft[j] = i, rgt[j] = i + 1;
	//3.计算每辆车的超速区间(本题核心)
	for (int i = 1; i <= n; ++i) {
		if (d[i] > p[m]) continue; //如果驶入的位置之后没有测速仪就不理它了
		if (a[i] == 0) {
			if (v[i] > V) {
				g[++ans1] = i;
				ld[i] = rgt[d[i]];
				rd[i] = m;
			} //一开始就超速
		} else if (a[i] > 0) {
			if (v[i] > V) {
				g[++ans1] = i;
				ld[i] = rgt[d[i]];
				rd[i] = m;
			} //一开始就超速
			else {
				tmp = V * V - v[i] * v[i];
				if (tmp % (2 * a[i]) == 0) {
					tmp = d[i] + tmp / (2 * a[i]); //当车行驶到这里时提速到V
					if (tmp < p[m]) {
						g[++ans1] = i;
						ld[i] = rgt[tmp + 1];
						rd[i] = m;
					} //在p[m]处恰好提速到V是不算的
				} else {
					tmp = d[i] + tmp / (2 * a[i]) + 1;
					if (tmp <= p[m]) {
						g[++ans1] = i;
						ld[i] = rgt[tmp];
						rd[i] = m;
					}
				}
			} //加速了一会儿才超速
		} else {
			if (v[i] > V) {
				tmp = v[i] * v[i] - V * V;
				if (tmp % (-2 * a[i]) == 0) {
					tmp = d[i] + tmp / (-2 * a[i]);
					if (tmp > p[m]) {
						g[++ans1] = i;
						ld[i] = rgt[d[i]];
						rd[i] = m;
					} else {
						ld[i] = rgt[d[i]];
						rd[i] = lft[tmp - 1];
						if (rd[i] >= ld[i]) g[++ans1] = i;
					}
				} else {
					tmp = d[i] + tmp / (-2 * a[i]);
					if (tmp >= p[m]) {
						g[++ans1] = i;
						ld[i] = rgt[d[i]];
						rd[i] = m;
					} else {
						ld[i] = rgt[d[i]];
						rd[i] = lft[tmp];
						if (rd[i] >= ld[i]) g[++ans1] = i;
					}
				}
			} //一开始超速,后面减速
		}
	}
	//4.计算最少需要开启的测速仪数量(贪心)
	sort(g + 1, g + 1 + ans1, cmp);
	for (int i = 1; i <= ans1; ++i)
		if (ld[g[i]] > id) {
			id = rd[g[i]];
			++ans2;
		} //如果左端点没有被覆盖到,那就在右端点覆盖
	cout << ans1 << " " << m - ans2 << endl;
}
int main() {
	cin >> t;
	while (t--) solve();
	return 0;
}


http://www.kler.cn/news/368064.html

相关文章:

  • 基于huggingface训练数据处理(load_dataset、map、data_loader等内容)
  • 多元线性回归【正规方程/sklearn】
  • 华为OD机试 - 芯片资源占用(Java 2024 E卷 200分)
  • 解决电脑更改IP地址后无法连接网络的实用指南
  • 2024 Rust现代实用教程:1.3获取rust的库国内源以及windows下的操作
  • 用接地气的例子趣谈 WWDC 24 全新的 Swift Testing 入门(一)
  • ES6:let和const命令解读以及变量的解构赋值
  • PostgreSQL(十三)pgcrypto 扩展实现 AES、PGP 加密,并自定义存储过程
  • Flink CDC系列之:学习理解核心概念——Transform
  • Elasticsearch 解析:倒排索引机制/字段类型/语法/常见问题
  • 双击热备和负载均衡的区别
  • 头歌数据库实验 MySQL
  • Redis 哨兵 总结
  • Vue3学习:番茄钟案例的实现及打包遇到的几个问题
  • Python 自动化运维:Python基础知识
  • Vuejs设计与实现 — 渲染器核心:挂载与更新
  • 【C++单调栈 贡献法】907. 子数组的最小值之和|1975
  • 闯关leetcode——171. Excel Sheet Column Number
  • Unity3D 自动化资源打AB包详解
  • Vue项目GET请求正常,POST请求却失效?揭秘Mock服务背后的故事
  • hass docker openwrt配置
  • C++,STL 050(24.10.27)
  • 【uni-app学习-2】
  • Golang | Leetcode Golang题解之第504题七进制数
  • Vue 如何批量注册自定义指令
  • 基础设施即代码(IaC):自动化基础设施管理的未来