ICPC2023南京站题解(A C D F G I L M)
本场金牌线为7题前一半。做出8题可稳金牌,这里是难度前8题的题解。
1|0ICPC2023南京站
1|1I:
签到题。
1|2F:
等价重写,可以轻松地想到本题和图论有关,每个操作修改的数字是独一无二的,因此每个覆盖事件都可以产生一个先后关系,我们可以将某个位置先写入的数字连向后写入的数字,在拓扑排序中就可以表示先写入较早的数字。
我WA了一发哈哈,因为没考虑完整,连边只需要连向每个位置最后覆盖的数字就行,之前谁把谁覆盖没有关系。
1|3C:
官方题解中给出了两种解法,都有思考价值。
解法一:
异或运算满足不等式:,那么我们把题目中的 g 写出来:,它也满足不等式:。
这个不等式能告诉我们什么?虽然我们的 异或上了 使得结果 g 的具体值不确定,但是 g 是有取值范围的,这个范围的大小不超过2P,随着 的增长,g 的取值范围左右各增加一个 P,也就是说,g 的取值范围接近上限 m 时,k 的取值就在 左右,小于这个值时,g 一定比 m 小,大于这个值时 g 一定比 m 大,在 左右时特判即可。
解法二:
这个做法是比较无脑且科技的,比较推荐:
将 [l,r] 这个区间的所有整数异或上一个值 X ,可以得到 log 段连续的区间。[0,m] 这个区间异或上 (P-1),每一段判断有多少 (kP+1) 即可。
1|4G:
可以免费选物品的背包,总感觉哪里做过。
假如从珠宝店出来,你拿着一些物品,把这些物品分为两类,一类是你买的,一类是你免费选的,那么可以肯定的是,你免费选的那些物品,一定是价格比较高的,这样省钱。
所以这两类物品是存在一个分界线的,是按价格排序的分界线。
枚举一个价格,设免费选的都高于这个价格,买来的都低于这个价格,那就高于这个价格的优先选价值高的,低于这个价格的用背包。
前者优先队列,后者朴素背包。
1|5A:
南京站四次重现,还挺酷的。
题目比较吓人,但是稍微想想会发现,如果我是袋鼠,我会把我能走到的地方都走一遍,如果还没有赢,那我就赢不了了。
我能走的区域就是四连通块,如果场内有能够包含我这个连通块的其他连通块,那我就成为不了赢家,反之肯定能赢,且我连通块内的其他袋鼠也一定能赢(这个很关键)。
枚举所有的连通块,扫一遍全图,每个位置判断需要花费我连通块大小的时间,设每个连通块大小为 ,总复杂度为 ,因为题目中 是 1000,所以平方可过。
1|6L:
这题思考难度是签到,但是难写程度甚至导致成为了银牌题。
电梯运包裹,因为包裹大小只有 1 和 2,且贪心满足要求,所以是可以排完序后直接模拟的,直接模拟的话可能会有些卡手,因为想使用两个set分别存 1 和 2 的包裹的话,来回选还是比较难写的。
我的做法把所有包裹放在一起按楼层排序,如何寻找最高的大小为 1 的包裹呢,想必大家都听说过树状数组二分这个东西吧?支持单点减(某个1包裹被运完),查询第k个数的值(查询楼层最大的1包裹的位置)。
但是我觉得麻烦没用树状数组,我是直接二分的,在前缀和上二分,找楼层最大的1包裹,因为答案是单调的,所以某个包裹被运完之后,我可以把二分的右区间改成这个楼层,这样就保证答案一定还没运完。
题解提供了避免区分 1 和 2 包裹的转化做法。因为保证电梯大小是偶数,这就诱使选手去思考下更简单的转化:如果我电梯只剩下1的空间,我挑选一个1包裹,和我把下一个2包裹拆成两个1,效果是一样的,都不影响最终答案。证明不难,也比较妙。最终结论就是,2包裹全拆成1包裹就行了,不用讨论了。
但是我想练练码力所以没转化。
1|7M:
好经典的题意,上一次见降雨存水的题好像是一道防AK几何。
好心的出题人怕大家做不出来,温馨地给了一个“更正式地”,其实是个关键的题意转化:, 分别表示前缀最大值和后缀最大值。这个转化是在枚举每一个位置上有多高的水柱。
更新 时,单独更新每一个位置的 是比较好更新的,可是它俩的 min 值就不是很方便更新,能不能进一步转化?
我们发现,本来就是左右的最大值,这俩已经包括了全局所有的数,那么对它们取个min,是不是跟全局次大值有关呢。
只要能想到这一点,不难转化成下式:, 表示全局最大值。。
因为 的修改只有增加,这就方便了我们对这三个值的维护,比如 是单增的,就可以用 set 维护,相同的数值只需在 set 中记录第一个位置。
1|8D:
凸优化的树上DP。
设 表示 u 这棵子树所有分支都有 i 个黑点的最小修改量, 表示把 u 这个点改成红点/黑点的代价。
有如下转化: 。
i 的取值是 u 子树中最短的分支,也就是说复杂度就是所有子树中最短分支的长度和,但显然当数据是链状结构时会卡死。
喜欢拿金牌的选手们会发现,这是个可以凸优化的DP,由于 DP 转移式子是将两个序列进行 (min,+) 卷积,满足闵可夫斯基和的形式,也就是两个凸包相加融合(这个在几何题中也比较常见),两个凸序列卷完还是凸序列,g 因为只有两个值所以一定是凸的,f 通过归纳自然也能证明是凸序列。
那么凸序列有什么好处呢?我们可以用 “差分序列加首项” 来维护一个凸序列,如果凸序列存在最小值,那么差分数列是单增的。回想几何中的闵可夫斯基和,我们将两个凸包上的每一条线段合在一起按斜率进行排序,序列上的 (min,+) 卷积也是如此,将首项相加,再将两个差分数列的每一个数合在一起排序,生成新的差分数列,即为卷积后 的序列。
回到这题的做法,我们每次求 序列,需要先将 直接相加,再和 做卷积, 直接相加只需要保留最短分支的长度即可(下面的代码中用 表示)。
这个做法最大的好处是,我们不会被链之类的数据卡掉,当我们只有一个儿子时,直接继承它的 数列即可。
然后是和 做卷积,分为两种:当 u 是红点时,往差分数列加入一个1;当 u 是黑点时,首项加1,再往差分数列加入一个-1。
最终答案,也就是 的最小值,等于首项加上差分数列最小前缀(所有负数相加)。为了避免使用平衡树维护,我们观察发现加入的数字只有1和-1,我们换个简单的写法,用三个vector来记录差分数列,一个从小到大记录负数,一个记录0,一个从大到小记录正数,加入1和-1只需在vector尾部插入即可。
思路可能比较经典,但是思考和实现难度都是妥妥的金牌题。
__EOF__

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)