9.10 模拟赛(炼石计划 11 月 15日 CSP-S 十连测 #10)

炼石计划 11 月 15日 CSP-S 十连测 #10【补题】 - 比赛 - 梦熊联盟 (mna.wang)

复盘

所有题先都浏览了一遍。其中 T1 见过。但当时是乱搞过的。但怎么乱搞的忘了。

那就先做 T1。有 60 分送的。尝试重新思考乱搞以获取剩余的 40 分。

中间看了一眼 T3。想了一分钟左右就会做了。这是一个很多套路集合的题。于是先放 T1 写 T3。

代码很短(40 行)。调了一小会就过了样例。时间还早(比赛刚进行不到一小时)于是先写对拍。

发现一个好东西:windows 可以切换桌面,你可以把对拍程序放桌面 2,其它放桌面 1。这样在你写别的程序时就不会被正在跑的 dp.bat 干扰了。尽管这不重要。

欸 T2 好像也见过类似的。反正做法一定是贪心,但贪心策略不明。部分分里有 24 分爆搜,先写这个。

有个 8 分的 n=102,m=105,c104。这是什么???分这么少的部分分我不会???反正是 8 分不要也罢。

尝试思考了一会儿正解。其弱化版 ci=1 是经典题,Acwing 算法基础课的最后几节有讲。那题的做法是按右端点排序然后能选就选。这两道题有关系吗?

不清楚。但如果延用这题的思路应该能不少分。于是写了一颗线段树。此时我的心态是保底 24 上限无限,但没不觉得能满分。

T4 一眼不会。写了送的 10 分就跑路了。

主线任务思考 T1 乱搞还没完成呢!最终也得到了一个需要用线段树维护的乱搞做法。但是对拍正确的概率很低很低很低

值得一提的是,写 T1 送的 60 分时差点给我送了。险些 10040

预计 60+eps,[24,100),100,10。实际 100,100,100,10???T1 数据这么水???

T3 正解 Trie???我的思路不更简单???

总结

好的:

  • 运气无敌。

不足:

  • T1 的暴力写了很长时间。写代码前要想清楚较为简介的实现方法不要上来就是一个线段树。
  • 给 T1 的乱搞做法写对拍时浪费了较长时间。

知识点

T1:暴力(?)优化

T2:贪心

T3:前缀和,位运算(Trie 树)

T4:贪心

题解

A. 体育课2

简洁题意:有 n 个人排成一排,每个人有一个权值构成了一个排列。每次对于每个人而言,如果他右面的第一个还活着的人的数小于自己的数,就把他杀了。求经过多少轮后没有人会死。

cnti 表示第 i 个人杀了多少人。那么答案为 maxcnti。考虑求解 cnt

对于排列 3,1,2,显然 2 被杀之前 1 会被杀。或者说只有 1 被杀了 2 才会被杀。这很像一个 flood fill 的过程。考虑队列维护。(或者认为是 bfs。)

在此同时维护链表,这有助于我们快速求出某个人后面第一个没死的人。

然后模拟即可。复杂度 O(n)

可能代码更有助于理解:提交记录 #610619 - 梦熊联盟 (mna.wang)

B. 零件加工

简洁题意:数轴上有 n 个数和 m 个区间。你需要选择尽量多的区间数量,使得每个点被覆盖的区间数量 ci

ci=1908. 最大不相交区间数量 - AcWing题库。这两题做法相同,将所有区间按照右端点升序排序,然后只要合法就添加。

贪心证明只会感性。

C. 优美的序列

简洁题意:求有多少区间异或和 k

套路求解前缀和 si=a1xorai。那么 (l,r) 需要使得 srxorsl1k

显然的也是 std 的做法是 Trie 树。但我没有。

运用类似数位 DP 的思想。在二进制视角下,如果 a>b,那么必然存在一个前缀使得 a,b 相同,且这个前缀的下一位满足 a1b0,后面无限制。

我们枚举 srxorsl1k 相同的前缀长度。因为后面的位无限制所以直接将 k,a1an 都右移这个长度。

得到新的 k,a1an,s1sn 后,问题转化成了:

  • 求有多少 (l,r) 使得 srxorsl1=k

这是平凡的。

因为用了 map 所以总复杂度两个 log。当然也可以用 umap。提交记录 #610551 - 梦熊联盟 (mna.wang)

D. 产品加工

考虑如果只有一道工序该怎么做。

考虑贪心。我们每次找到当前仍空闲的t 最小的机器操作即可。

实现上你可以维护一个堆。这份代码里 pair 的 first 维护的信息是:

  • 如果某件商品要用这个机器,那么这件商品将会在什么时刻完成制作。也就是在原来 t 的基础上加了排队的时长。
void solve(int *f, int *a, int n) {			// f[i] 表示第 i 件物品在什么时候制作完成
	priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> Q;
	for (int i = 1; i <= n; ++ i ) Q.push({a[i], i});
	
	for (int i = 1; i <= q; ++ i ) {
		int x = Q.top().first, y = Q.top().second;
		Q.pop();
		f[i] = x;
		Q.push({x + a[y], y});
	}
}

两道工序?

我们可以将两道工序分别跑一遍上面的流程。得到两个长度为 q 的数组 f,g

但是 f,g 的内部顺序是未定的。这是因为我们在求解时将所有商品都视作相同,但是两道工序拼起来后这样考虑就不对了。

对于一个物品而言,它所花的时间是 fi+gi。所以总流程花的时间是 max(fi+gi)。我们要最小化 max(fi+gi)

f,g 重排,使得 max(fi+gi) 最小是经典问题。f,g 一个升序排序一个降序排序即可。

posted @   2huk  阅读(71)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示