2026.8.12 模拟赛

https://oj.gxyzh.com/d/hzoj/contest/6a4600744de4613bd328ca15

yspm 的题解

T3 题解
T4 题解
T4 题解

这场打得是不太好,只有 30 分,暴力分不会打,应当反思.

T1 T2 T3 T4
实际得分 20 10 0 0
期望得分 20 10 0 10
能力得分 100 25~100 20 40

第负一题

求区间最大带权独立集的总和.

由于是独立集问题,考虑 DP;由于总共有 \(O(n^2)\) 个区间,因此考虑使用分治优化(猫树分治).

对于所有区间,将其拆成在 \(mid\) 左右两侧两部分.

记 \(g_{i,0/1}\) 表示左右区间中,第 \(i\) 位,钦定取/不取边界点的最大贡献,使用 DP 辅助是已于求出的.

那么区间 \([L,R]\) 的贡献为 \(\max\{g_{L,0}+\max(g_{R,0},g_{R,1}),g_{L,1}+g_{R,0}\}\).

考虑固定左端点,统计右端点的贡献:
当 \(g_{L,0}+\max(g_{R,0},g_{R,1})\ge g_{L,1}+g_{R,0}\) 时选取第一种贡献.
移项可得:\(\max(g_{R,0},g_{R,1})-g_{R,0}\ge g_{L,1}-g_{L,0}\).
将左侧的排序,二分出边界,使用前缀和统计.

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

数树

场上不会写 35 分的状压.

对于这道题,由于存在边的约束条件,而这种条件不好处理,故考虑容斥.

由于 \(a_v=a_u+1\) 时是不合法的边,因此不合法的边构成若干条链.

设 \(F_i\) 表示有 \(i\) 条边不合法,\(G_i\) 表示钦定 \(i\) 条边不合法的方案数.
\(F_i\) 与 \(G_i\) 之间可以通过容斥转化,现在考虑求 \(G_i\).

考虑如果我们知道了有 \(j\) 条边是不合法的,那么树会被划分成 \(n-j\) 条链,那么染色方式只有 \((n-j)!\) 种,现在我们要求钦定 \(j\) 条边不合法的方案数.

这是可以使用 DP 解决的,设 \(dp_{i,j,0/1/2/3}\) 表示对于节点 \(i\),子树内有 \(j\) 条边不合法,以及节点 \(i\) 的状态:

  1. 子树内没有相邻的边;
  2. 子树内相邻的边只有一条出边;
  3. 子树内相邻的边只有一条入边;
  4. 子树内相邻的边只有一条出边,一条入边;

使用树上背包,时间复杂度为 \(O(n^2)\).

石子游戏

这是多堆 Bachet 游戏,因此可以使用 \(SG\) 函数:

\[SG_x(a_i)=(a_i\bmod (x+1)) \]

若异或和为 \(0\),则后手赢,否则先手赢.

即我们需要求:

\[\oplus (a_i\bmod k) \]

将 \(\bmod\) 拆开:

\[\oplus (a_i-\left \lfloor \frac{a_i}{k} \right \rfloor k) \]

由于有 \(\frac{a_i}{k}\),故考虑枚举这一维,则时间复杂度为 \(O(n\log n)\),
即 \(\left \lfloor \frac{a_i}{k} \right \rfloor=r\),枚举 \(a_i\in [rk,(r+1)k)\).

可以先对值域做一个异或 \(c_i\),之后考虑统计:

\[\oplus (a_i-rk) [a_i\in [rk,(r+1)k)] \]

考虑按位统计,设 \(f_{i,j}\) 表示:第 \(j\) 位的 \(\oplus (k-i)[c_k]\) 的值.
记 \(o(L,R)\) 表示区间 \([L,R]\) 中数的个数的奇偶性.

则有如下转移:

\[f_{i,j}=o(i+2^j,i+2^{j+1}-1)\oplus f_{i+2^{j+1},j} \]

考虑统计对于区间 \([L,R]\) 的答案:
记 $z=\left \lfloor \frac{R-L}{2^{j+1}} \right \rfloor $

\[f_{L,j}\oplus f_{L+2^{j+1}(z+1)-1,j}\oplus o(\max(r,l+2^{j+1}z+2^j-1)+1,l+2^{j+1}(z+1)-1) \]

时间复杂度 \(O(n\log n\log n)\),可以进行剪枝.

子段和

这道题是比较好的,当然也是比较史的.

首先考虑对于每一个 \(K\) 统计 \(g(K)\):
将 \(a_i\) 序列进行前缀和,那么每次操作就是后缀减,最大子段和就是:\(\max_{i<j}(a_j-a_i)\).

考虑二分答案,设 check 的最大子段和为 \(w\):
可以使用如下方法进行 check,需要满足 \(\forall i<j,a_j-a_i\le w\):
从前向后贪心,维护 \(lim\) 表示后缀的最大值,\(cnt\) 表示操作次数:

  • 若 \(a_i>lim\),则将 \(a_i\) 及后缀减去 \(a_i-lim\).
  • 令 \(lim=\min(lim,a_i+w)\)

事实上我们不需要每次将后缀操作,只需要令 \(lim=a_i\) 即可.

时间复杂度为 \(O(Kn\log w)\).

考虑优化:
记上面的 check 时的函数为 \(c(w)\),表示将最大子段和变成 \(w\) 的最小操作次数.
由于惊人的注意力:发现 \(c(w)\) 是单减的,并且斜率也是单减的,并且斜率不超过 \(n\).
因此可以处理出每一种斜率的位置,时间复杂度为 \(O(n^2\log w)\).

继续考虑优化:
现在复杂度的瓶颈在于求 \(c(w)\) 单次是 \(O(n)\),需要优化.
考虑将所有 \(c(w)\) 放在一起统一求出:
记 \(lim(w)\) 与 \(cnt(w)\).

  • 初始时,\(lim(w)=w\),构成斜率为 \(1\) 的线段.
  • 对所有 \(lim(w)<a_i\) 统计答案,并统一修改为 \(a_i\),构成斜率为 \(0\) 的线段.
  • 对于所有 \(a_i+w<lim(w)\) 的 \(lim(w)\) 统一修改为 \(a_i+w\),是斜率为 \(1\) 的线段.

综上,\(lim(w)\) 总是构成若干条斜率为 \(0/1\) 的线段.
并且每次修改均是修改前缀的 \(lim(w)\),替换成一条新的线段.
这个过程可以使用单调栈维护,使用线段树统计 \(cnt(w)\).

之后查询 \(c(w)\) 时,在线段树上查询即可,单次复杂度为 \(O(\log w)\).

综上,总时间复杂度为 \(O(n\log^2 w)\),卡卡就过了.

posted @ 2026-08-12 20:53  Zhou_Lemon  阅读(15)  评论(0)    收藏  举报