Solution Set - 贪心和数据结构
感觉自己好菜啊,这个专题真的不太会。
CF1439C Greedy Shopping
容易发现,当此人连续买了一段物品之后,他的钱数至少减半。所以他最多只会买 段物品。那么就可以直接模拟每次询问,不断往后轮流找最多能买到的位置和下一个能买的位置。二者都可以线段树上二分,维护前缀和最大值和区间最大值。修改也是容易的。时间复杂度 。
CF436E Cardboard Box
考虑贪心,每次取当前能够取的代价最小的星。然而这肯定不对,所以打一个补丁:如果某个两星代价比最小的两个一星之和小,那么就先把它玩到一星。注意如果只差一颗星了是不采用这个策略的。正确性还是比较显然的。
CF1452G Game On Tree
先做一次多源BFS,求出Bob占领每个点的最小时间 。如果点 满足 ,那么Alice从 开始可以先于Bob到达 ,这样就可以用 更新 为起点的答案。考虑点分树,记下每棵子树内的所有点及距离并排序,然后从每个点开始跳父亲,能更新的是一段前缀。直接二分即可。时空复杂度都是 。
CF625E Frog Fights
模拟,用一个链表维护所有青蛙。把发生“撞飞”的时间记在一个堆里,不断取堆顶模拟,更新链表和堆。
一个实现时的细节是,当一只青蛙撞飞另一只青蛙后,直接把它的初始位置往右移动经过的时间即可。
CF533A Berland Miners
根到每个点的路径上有一个瓶颈,就是这条路径上的最小点。对每个点开一个vector,记下以它为瓶颈的所有路径。假设选择 增加一些,那么会导致一些路径的最小高度增加,这些路径一定都以 为瓶颈。一些路径仍然以 为瓶颈,其余的路径的最小高度会变成它的次小值。从小到大枚举 变成的高度,用权值线段树维护。具体来说,人的高度位置加上一个 ,路径的高度位置加上一个 ,则后缀和始终非负时有方案。如果 变成某个高度时有方案了,那么上一个高度最后一个后缀和为负的位置就是 需要变成的最小高度。
CF1427F Boring Card Game
首先不考虑轮流操作的限制,容易用栈模拟出一种方案:从左往右向栈里加数,如果栈顶的三个数属于同一个人就弹出栈顶。这样的方案肯定是存在的,因为保证了有解。
对于一组数 ,考虑完全包含在区间 内的数组。在直接包含的数组间连边,得到一个森林。要求必须先取儿子再取父亲。显然有边相邻的两组数不会属于同一个人,那么轮流剥叶子就可以了。
CF671E Organizing a Race
先考虑固定一个区间如何最小化增加量。从左往右扫,当某一段路开不过去的时候就给上一个点加油。也就是说每次都选择尽可能右边的点加油。最后如果还有剩的,全部留给右端点就行。
考虑用前缀和刻画,会发现选择加油的点可以用单调栈维护。那么从右往左扫描,维护单调栈,就可以用线段树维护出后缀和进行判断。固定左端点,假设已经通过加油使得左端点可以一直向右。先二分出一个最远的位置,使得到达它需要增加的量不超过 。然后会发现一个事情:如果一个区间内有解,那么初始最大值最大的位置一定是解。 事实上我们要求的是右端点的后缀和最大,而右端点加了 ,前面的点加的都不超过 ,所以上面这个结论成立。直接在线段树上二分即可。
以上用自然语言描述了算法的框架,进行列式会更好理解。
CF1548E Gregor and the Two Painters
我们在连通块内权值最小的位置统计答案。 一个点能够成为连通块内最小的点的条件是:首先它得是黑点,其次它不能只经过黑点到达一个权值比它小的点。如果权值相同,把横坐标作为第二关键字,纵坐标作为第三关键字。
会发现要进行这个判断,只要考虑单独往一个方向的情况。要求往上下左右都不能到达更小的位置。具体来说,假设考虑的点是 , 左边不大于他的第一个点是 ,右边小于它的第一个点是 ,则要求 不能到达 ,再加上对 类似的限制即可。
要“到不了”,就要求路径中间有一些不是黑点。记 ,对 类似定义 。要求 。离线二维数点解决。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具