2024.10.3
Last Update:
Word Count:
Read Time:
模拟赛
数据范围:
值域很大,无法加到状态里。那么考虑每个操作对答案产生的贡献。
我们把攻击力拆开来算。
直接攻击,那么贡献就是 。
设这回合后一共攻击 次。
加攻击力,那么在这以后每次攻击伤害都会加 ,贡献就是
加增量,那么设后续攻击的回合是 ,那么贡献为 。
把这个东西稍微拆一下,得到 。
那么我们只需要记录攻击次数和攻击回合的编号和即可。
但有个问题,我们现在的贡献和未来回合的行动有关。
所以要倒过来做。那么转移也要相应的变一下。
设 表示第 个回合到最后一个回合,一共攻击了 次,攻击回合的编号和为 的最大值。
转移为
转移时可以把第一维压掉,但第二维要倒序枚举。
复杂度 。
Code:
1 |
|
Removing Leaves *2300
又读错题被硬控了。
一开始没看见 ,以为随便删。
考虑贪心。
我们用 set 存每个节点,然后每次找到叶子最多的那个点,然后删 个。找不到就结束。
这为什么是对的?
感性理解一下,我们这么做只会让能删的点越来越多,而且不会有本来能删的点因为操作而不能删除,所以这么做操作数就是最大的。
复杂度
Voting (Hard Version) *2400
看完题就想到了一个假贪心:先按 降序再按 升序,每次买 最大 最小的。
显然不对。我们不一定只从 最大的里面买。
那改成每次买 最小的呢?
还是不对。因为不一定买最小的就优。例如这组样例
1 |
|
显然只需要 即可。
那应该怎么做?
我们依旧按 降序排序。
对于当前的 ,设 值小于 的人数为 ,大于 且被买的人数为 。
假设我们已经把 的人全搞定了,那么只需要让 ,就能搞定 了。
但如果不满足,我们就要从 的人里买人(因为 是固定的),直到 。
满足该条件后, 就被我们搞定了。
那么我们只需要保证 的人都被搞定就行了。
然后再处理 的那些人。这是一个子问题,和上述步骤完全一致。
买人贪心买最便宜的,用个堆维护一下即可。
复杂度
Happy Life in University *2300
怎么现在啥数据结构都不会了/kk。
对于这种 lca 的问题,常见套路是枚举 lca,把贡献都在 lca 处统计(枚举 lca 的意思是考虑每个点作为 lca 时的情况)。
而这种 lca 的路径问题又能跟子树弄上关系。
设当前考虑到以 为根的子树。
那么我们只需要维护 到子树内节点的路径即可,答案就是拿两条路径拼起来。
假设已经搜完了子树,回溯到了 。
那么 会对所有路径产生自己颜色的贡献。
但显然会算重,那么考虑去重。
因为每个点只需要在离他最近的且颜色和他相同的祖先处减去重复,所以只会操作 次。
那么直接去重就是对的。
所以我们的操作就只有子树加和子树查,线段树维护。
答案用最大值和次大值拼一下即可。
复杂度
Wine Factory (Easy Version) *2300
讲一个很有意思的做法。
我们考虑有多少水被浪费了。
设 表示从 流向 的水的量。
转移为
这东西可以用 矩乘表示。
然后线段树维护矩阵即可。单点修改也是简单的。
复杂度
Mark and Professor Koro *2300
感觉和 [HBCPC2024] Enchanted 非常的像啊,套路也是一样。
对于这种两个相同的数合并成+1的数的操作,我们可以把它看成二进制意义下的加法,然后进行维护。
但这个题不能直接把数的二进制用整数表示,值域太大了。
我们用线段树维护值域上每个数出现次数,不难发现每个数出现次数只会为 0/1。
那么修改可以看成删一个数再加上一个数。
删和加是类似的,先考虑加。设加的那个数是 。
如果 那一位是 0,那么不用进位,直接给这一位 +1 即可。
否则会进位。但不难发现,这东西是一次区间覆盖和一次单点修改。
删数同理。
如果 那一位是 1,那么不用退位,直接给这一位 -1 即可。
否则会退位。依旧是一次区间覆盖和一次单点修改。
那么答案就是最右边的 1 的位置,这个可以线段树上二分找到。
具体的,线段树上维护区间里 1 的个数。
加法进位:找到 后第一个为 0 的位置 ,然后把 区间赋值为 0,把 赋值为 1.
减法进位:找到 后第一个为 1 的位置 ,然后把 区间赋值为 1,把 赋值为 0.
找位置都可以线段树上二分。
复杂度