2026.7.9 模拟赛

先放一个题解链接
https://www.cnblogs.com/high-sky/p/19149902

https://hszxoj.com/d/hztg/contest/6a4e1f562591873b0a1175ca

这场比较去世,没有 A 一道题,T1 不知道神秘原因错误,T2 理解错题意,T3 一直在想多项式和拉插,T4 60分暴力挂成 20 分(然而直接模拟可以拿到 80 分).

白露澈明之泉 (fountain)

场上一直没有读懂题,以为列也可以转化成行(事实上这样不太可做,复杂度至少要达到 \(O(\frac{n^3}{w})\),过不去).

其实读懂题之后,这道题比较简单.

显然我们应当先构造出一行 1,之后才能将其转化成列.
我们可以枚举是哪一行全是 1,我们维护这些信息即可完成:

  • ct 有多少列不全是 1;
  • cnt[i]\(i\) 行有多少个 1;
  • has[i]\(i\) 列有无 1;

枚举行 \(r\),则有:

\[ans=\min_{r=1}^n n-cnt_i+ct+[has_i=0] \]

时间复杂度为 \(O(n^2)\).

概率 (pr)

设前 \(n\) 个数和为 \(A\),后 \(n\) 个数和为 \(B\),我们所求的即为 \(P(A>B)\),不难发现上面的概率具有对称性,即有 \(P(A<B)=P(A>B)\),因此 \(P(A>B)=\frac{1-P(A=B)}{2}\).

如何求 \(P(A=B)\)?不难发现总情况数是已知的,现在需要求满足 \(A=B\) 的情况数 \(ans\).可以使用 DP,设 \(dp_{i,j}\) 表示前 \(i\) 个数,和为 \(j\) 的情况数,因此:

\[ans=\sum_{i=0}^{nm}dp_{n,i}^2 \]

时间复杂度为 \(O(Tn^2m)\),可以拿到 50 分.
如果你注意到 \(dp_{i,j}\) 具有对称性,剪枝之后可以拿到 70 分.

这里给出一种容斥原理的满分做法:

如果我们继续按照上面枚举最终形成相等序列的和是没有前途的,因为值域是 \(O(nm)\) 的.

考虑转化,若有 \(A=B\),讲后半部分的值域进行翻转,即令 \(a_i=m-a_i\),这样会有什么规律呢?有 \(\sum_{i=1}^{2n}a_i=nm\),同时有 \(a_i\le m\)(这个思想有些类似于将差卷积转化为和卷积的过程,目的将其转化为和的关系),这就是一个经典容斥问题.

考虑如果没有对 \(a_i\) 的值域限制,那么就是一个隔板法,共有 \(\binom{nm+2n-1}{2n-1}\) 种情况.
如果有对 \(a_i\) 值域的限制,考虑钦定至少有 \(k\) 个人超出 \(m\),即大于等于 \(m+1\),那么我们将超出的部分拿掉,剩下就是另一个隔板法,共有 \(\binom{nm-k(m+1)+2n-1}{2n-1}\) 种情况.
使用广义容斥/二项式反演,则有:

\[ans=\sum_{i=0}^{n}(-1)^{i}\binom{n}{i}\binom{nm-k(m+1)+2n-1}{2n-1} \]

提前对组合数预处理(设上界为 \(K\)),可以得到 \(O(K+Tn)\) 的时间复杂度.

神谕 (oracle)

比较有趣的数据结构题,帮我回忆了树上差分(话说学了树剖之后很少用树上差分).

对于子任务 1,可以暴力模拟,理论可以拿到 40 分(通过子任务 1、4).

对于特殊性质 1(构成一条链的情况),这时可以模拟懒标记的位置,每次 add 时暴力 push_down,使用线段树/平衡树 优化(因为操作 \(O(q)\) 次,至多有 \(q\) 个懒标记),时间复杂度是 \(O(n+q\log n)\),但是场上没有调过.

对于特殊性质 2(每次操作都是对一个节点操作),不难发现这样也至多有 \(q\) 个懒标记,使用树剖暴力模拟,时间复杂度是 \(O(n+q\log^2 n)\) 的(也就是说,性质 2 是对性质 1 是包含关系).

现在考虑正解,题解给出的做法是:使用标记永久化,统计根链上产生的贡献.

我们需要知道两个时刻:

  • \(\operatorname{leavetime}\):最近一次 将标记下传到儿子,自己标记清空 的时刻.
  • \(\operatorname{entertime}\):最近一次 父节点将标记下传给自己 的时刻.

不难发现有:\(\operatorname{leavetime}_{fa}=\operatorname{entertime}_u\).

\(F(t)\) 表示在 \(t\) 时刻,根链上的标记数量,那么询问答案为:

\[a_u+F(\operatorname{entertime})-F(\operatorname{leavetime}) \]

因此我们只需要考虑 \(\operatorname{leavetime}\)\(F(t)\) 怎么求.

\(\operatorname{leavetime}\)
考虑哪些节点会受到影响,下面直接给出结论:
若操作的区间为 \([L,R]\),则受影响的节点为 \(LCA(p_{L-1},p_{L})\)\(LCA(p_{R},p_{R+1})\) 根链上的节点,其中 \(p_x\) 表示 \(x\) 对应的叶子节点.
因此我们可以对根链修改,单点查询,即可求出 \(\operatorname{leavetime}\).
可以优化:将时间标记永久化,查询时查询子树 \(\max\),这样可以做到 \(O(q\log n)\).
有了 \(\operatorname{leavetime}\),我们就可以求出 \(\operatorname{entertime}\).

\(F(t)\)
这是不能暴力的,因为标记数量是 \(O(n)\) 的.

由于直接求 \(F(t)\) 是困难的,考虑修改 \(F(t)\) 的定义:
\(t\) 时刻与区间 \([L,R]\) 有交的区间加的 \(k\) 的贡献.

为什么这样定义不会对最终答案产生影响?
考虑实际上我们要求的是包含 \([L,R]\) 的区间,这才是累加到根链上的贡献,但是这样不可做.
考虑不包含 \([L,R]\) 但有交的区间,这些区间的标记一定是打到 \([L,R]\) 的子树中,因此此时一定将 \([L,R]\) 的标记下传,即有 \(\operatorname{leavetime}=\operatorname{entertime}\),贡献是可以被抵消的.

而求解 \(F(t)\) 就是容易的:
\(total\) 表示 \(k\) 的和,设查询区间为 \([L,R]\),容易有:

\[total-\sum_{r<L}k-\sum_{R<r}k \]

可以使用 可持久化线段树/扫描线 来完成.

综上,时间复杂度为 \(O((n+q)\log n)\).

posted @ 2026-07-10 09:07  zhoumengxuan  阅读(9)  评论(0)    收藏  举报