2025.4.12 CWOI 模拟赛 T1 - T4
T1 倒水
我们先简化一下操作,其实本质上,操作只有六种:\(+x,+y,+z,-x,-y,-z\),并且代价都是 \(2\),\(-x,-y,-z\) 每出现一个就需要减 \(1\)。
那这就可以 DP 了,记 \(dp _ {i,S}\) 表示容量为 \(i\),减操作出现状态为 \(S\) 的最小代价。我们先处理加操作,则 \(dp _ {i,0} = \min (dp _ {i,0},dp _ {i - x/y/z,0} + 2)\)。
然后考虑减操作,倒序枚举,\(dp _ {i,S \vee x/y/z} = \min (dp _ {i,S \vee x/y/z},dp _ {i + x/y/z,S} + 2)\)。最后统计答案,先记录一个 \(res\),然后拿 \(dp _ {i,S} - \text{popcount}(S),dp _ {i,S} \neq +\infty\) 去更新 \(res\),如果 \(res = +\infty\) 就无解。
T2 让他们连通
板子题。
我们需要求一个区间内的点在多久联通,换言之,就是求只经过加入时间 \(\le x\) 的边能使该区间内点互达的最小的 \(x\)。这个就是 Kruskal 重构树干的活。以加入时间为边权,用最小生成树建出 Kruskal 重构树,然后求区间 LCA,可以用 ST 表来维护。
理论可以给我干到 \(\Omicron(n \alpha) - \Omicron(1)\) ?瓶颈在并查集,(区间)LCA 可以用两个 lxl ST 表搞到 \(\Omicron(n) - \Omicron(1)\)
T3 通信网络
赛时有个大概思路但是没有写,凹 T1 去了,还有逆天出题人分不清有序无序。
满足条件的最大值一眼二分答案,先二分一个 \(P\),然后枚举每个点 \(u\) 作为中继点的情况,遍历每棵子树,求出其中 \(w _ i \le w _ u + P\) 的个数,先更新 \(ans\) 再更新 \(cnt\),最后判断中继点本身是否满足,满足给答案加上 \(cnt\),最后如果 \(ans \ge k\) 就不合法,调小二分限制。
明显可以主席树做到双 \(\log\),但是过不去,单 \(\log\) 不会。
Update on 2025.4.14:收回双 \(\log\) 过不去的话,这其实可以过。只需要大力的卡常即可。
首先我们可以试试循环展开,读入 \(w\) 等是可以并行的,循环展开优化一下;然后不要 #define int long long
,可以 \(70 \to 90\);vector
存图加边太慢了,前向星存图求子节点太慢了,所以可以用宋佳兴在集训队论文中写的更加快速的存图:先把 \(u,v\) 记录下来,然后记录点的度,记个前缀和,然后 \(\forall u _ i,v _ i,g _ {d _ {u _ i}} \gets v _ i,d _ {u _ i} \gets d _ {u _ i} - 1\),\(v\) 也同理,然后 \(u\) 的子节点就全部在 \([d _ u,d _ {u + 1})\) 之间,内存连续,加边和遍历都很快。
因为线段树只有最后一层才没有 \(l \lt r\),所以可以加个 [[likely]]
的分支预测,然后就能以还剩下 \(10\) 多毫秒的好成绩卡过去。
T4 3SUM
原题 ARC180D。
我们把分出来的三段叫做 \(A,B,C\),区间内最大值记为 \(t\),最左边的最大值的位置为 \(p\)。
分三种情况讨论:
\(t \in A\):
我们发现,对于这种情况,扩大 \(A\) 一定不劣,并且 \(B\) 长度越小则代价越小,则 \(B\) 长度一定为 \(1\)。
因此答案为 \(t + \min _ {i = p + 1} ^ {r - 1} (a _ i + \max _ {j = i + 1} ^ r a _ j)\)。
发现右端点不动,因此我们可以把所有右端点为 \(r\) 的询问扔进一个 vector
,然后从小往大枚举 \(r\),到一个点有询问就去更新这个询问,用线段树维护后面那一堆。
\(t \in B\):
我们可以直接把 \(B\) 扩大为 \([l + 1,r - 1]\),然后答案就为 \(a _ l + a _ r + \max _ {i = l + 1} ^ {r - 1} a _ i\),上面也需要一个 RMQ 所以一起跑一个 ST 表。
\(t \in C\)
把原序列和询问翻过来然后当 \(t \in A\) 做。