一堆模拟赛题解
第一场
也许 / CF1320F
对于一个观测器,用 dfs 扫对应的一排。设观测到的值为 $t$,扫到了格子 $(i,j,k)$,颜色为 $c_{i,j,k}$。如果没被扫到过,则 $c_{i,j,k}=0$,如果这个格子被确认没有小立方体,则 $c_{i,j,k}=-1$。
对每个有颜色的格子存这个六个面上直接观测到这个格子且颜色与这个格子颜色相同的面有哪些。删除一个格子即将这些面的观测器继续向对应方向扫就行了。
扫的时候要删除的情况有:
- 这个观测器观测结果为 $0$;
- 这个观测器观测结果与其它观测器观测到这个格子的结果不同。
无解的情况就是一个观测到颜色的观测器所在的排全都是 $-1$。
注意到一个面只会产生 $O(nmk)$ 的复杂度,所以总时间复杂度 $O(nmk)$。
意识 / CF1344F
用 $0,1,2,3$ 表示 W(.)/R/Y/B
。
不难发现混合一个序列的结果就是他们的异或和。
mix
相当于提供了一堆值域为 $[0,3]$ 的异或方程组,不好解,考虑拆一个 $[0,3]$ 的变量为两个 $[0,1]$ 的变量。
设对于一个数,初始时高位是 $a_i$,低位是 $b_i$。
RY
:交换 $1,2$,即 $\text{swap}(a_i,b_i)$;RB
:交换 $1,3$,即 $a_i\gets a_i\text{ xor } b_i$;YB
:交换 $2,3$,即 $b_i\gets a_i\text{ xor } b_i$;
设当前 $i$ 位置的值的高低位为 $a_i',b_i'$ 则每个 $a_i',b_i'$ 都能用 $pa_i\text{ xor }qb_i$ 表示($p,q\in[0,1]$)。
就能列出线性异或方程组求解,注意判断无解情况。bitset
加速求解,时间复杂度 $O(\dfrac{n^2q}{w})$。
旅船 / CF936E
将一堆 $x$ 坐标相同的极长 $y$ 连续段格子缩成一个结点表示,给相邻的结点以及相邻的给出的格点分别连边(注意区分)。注意到题目给出的限制使结点组成的连通图无环,即它是一颗树。
考虑题目中操作的形式,对它建立点分树求解。每个结点 $i$ 维护点分树中 $i$ 的子树里(包括 $i$)的黑点到 $i$ 的最短距离,每次跳点分树查询即可。
设格点 $k$ 所在的结点为 $b_k$,记两格点 $x,y$ 间的距离 $D(x,y)$,记格点 $x$ 到结点 $A$ 的任意一个格点的最短距离为 $d(x,A)$,记 $p(x,A)$ 为使得 $D(x,p(x,A))$ 最小的且满足 $b_{p(x,A)}=A$ 的格点的 $y$ 坐标(可证其唯一)。则 $D(x,y)=d(x,P)+|p(x,P)-p(y,P)|+d(y,P)$。
我们需要求出所有的 $d(i,P),p(i,P)$,注意到 $P$ 一定是 $b_i$ 在点分树上的祖先,所以点分时从分治中心的所有格点开始 bfs 即可求出所有需要的 $b,p$ 了。
我们需要维护某种数据结构以查询 $\min D(x,p)$,其中 $p$ 为询问点,$x$ 为点分树中跳到的祖先的子树内的黑点之一。注意到绝对值很烦,可以拆掉,查询前后缀的 $\min$,用树状数组维护。不用担心 $x,p$ 来自同一子树,这种情况下它们一定在之前就被算过了。
需要卡卡常数,时间复杂度 $O((n+q)\log^2 n)$。
战车 / CF715E
对于 $\text{sub 1}$,连边 $p_i\to q_i$,则相似度为 $n-c$,$c$ 为形成的图的环数。
直接连边 $p_i\to q_i$,形成若干条以 $0$ 或其它数开头或结尾的链,设形成 $(0,0),(0,y),(x,0)$ 型链的数量分别为 $c_{0,0},c_{0,1},c_{1,0}$,已经形成的环的数量为 $c$。对于 $(x,y)$ 型链,我们将 $x,y$ 视作同一个数,即不管这种链,显然答案不变。
设 $f_i$ 为用完所有 $c_{0,1}$ 链,形成 $i$ 个环的方案数。不好求,考虑求 $g_i$ 为钦定形成 $i$ 个环的方案数,则可以得到:
$$g_i=\sum_{j=i}^{c_{0,1}}\binom{c_{0,1}}{j}{j\brack i}\binom{c_{0,0}+c_{0,1}-j}{c_{0,0}}(c_{0,1}-j)!$$
其中含义为:
- 枚举选出的链数 $j$ 构成钦定的 $i$ 个环;
- 将 $j$ 条链塞入 $i$ 个环;
- 剩下的链随意连接完即可,$(0,x)$ 可以和 $(0,x)$ 或者 $(0,0)$ 连接形成 $(0,x)$ 或 $(0,0)$(不影响 $(0,0)$ 链数)。
二项式反演得到 $f$。
同理求出 $c_{1,0}$ 链形成的环的方案数 $f'$。
求出 $c_{0,0}$ 构成 $i$ 个环的方案数 $f_i''=\displaystyle{c_{0,0}\brack i}c_{0,0}!$,含义为:
- 将链分给环;
- 链之间有区别。
对于三个数组做背包即可。时间复杂度 $O(n^2)$。
第二场
硬币 / CF1270H
引理:如果 $i,j(i<j)$ 连通,则 $i,k$ 和 $k,j$ 均连通($i<k<j$)。
分讨一下就证完了。所以连通块是若干连续段。问题即转化为求有位置 $p$ 满足 $\displaystyle\min_{i=1}^{p}a_i>\max_{i=p+1}^na_i$。枚举 $v$,将 $\le v$ 的标为 $0$,大于 $v$ 的标为 $0$,即求有多少序列中存在的 $v$ 使得序列形如 $11...100...0$,不妨令 $a_0=+∞,a_{n+1}=-∞$,则合法序列中相邻的 $10$ 对数恰好为 $1$。求出每个 $v$ 形成的序列中的相邻 $10$ 数量,统计有多少个是 $1$,发现最小值不可能比 $1$ 小,则维护最小值和最小值个数即可。
求每个 $v$ 形成的序列中的相邻 $10$ 数量即将所有 $[a_i,a_{i+1})$ 的区间加一。带修把原贡献删去加入新贡献即可。区间加,全局最小值及最小值个数,线段树维护,时间复杂度 $O((n+q)\log v)$。
转换 / CF1458E
当 $n=0$ 时就是 Nim 游戏,直接判断 $x,y$ 是否相等即可。
考虑第一象限内所有整点 $(x,y)$,若局面 $(x,y)$ 先手必胜则染白,否则染黑。当 $n=0$ 时我们发现黑点在 $y=x$ 上。
考虑 $n=1$ 怎么做:设给定局面为 $(a,b)$,则将 $(a,b)$ 染黑,将 $(a,p),(q,b)(p>b,q>a)$ 染白(能走到必败点),总有一个黑点被染白,不妨假设 $a>b$,则该点为 $(a,a)$,则 $(a+1,a)$ 会被染黑(不能走到必败点),$(a+1,a+1)$ 会被染白(能走到必败点),以此类推。
此时黑点形成的图像为 $y=\begin{cases}x&x<a\\x-1&x>a\end{cases}$,相反,若 $a>b$,则此时黑点形成的图像为 $y=\begin{cases}x&x<b\\x+1&x\ge b\end{cases}$,若 $a=b$,则此时黑点形成的图像为 $y=x(x\ne a)$。
$n$ 更大的情况也是像这样复合出来的,我们需要把这个函数求出来。考虑涉及到给定局面在当前函数上方还是下方,我们需要按照 $\max(a,b)$ 递增的顺序来求解。
我们将所求转化为以下问题:
有若干个点对 $(a_i,b_i)$,需要依次进行 $n$ 次以下操作:
- 取出 $\max(a_i,b_i)$ 最小的点对 $(a,b)$;
- 将所有点对的 $a_i$ 减一,或者将所有点对的 $b_i$ 减一。
设将所有点对的 $a_i$ 减一 $d_a$ 次,或者将所有点对的 $b_i$ 减一 $d_b$ 次,对于初始点对 $(a,b)$,如果 $a-b>d_a-d_b$ 则此时的 $a'>b'$,其它情况同理。进行第一步操作需要查询一个前缀中 $a_i$ 最大的点对和一个后缀中 $b_i$ 最小的点对,用线段树维护。进行第二步操作直接修改 $d_a,d_b$ 就好了。
求出所有 $x,y$ 方向的折点,查询时查询有多少 $x$ 的折点小于 $a$,$y$ 的折点小于 $b$ 就好了。
时间复杂度 $O((n+q)\log n)$。
毁灭 / CF793G
网络流,从 $S$ 向每行连流量 $1$ 的边,然后每行向这行合法的列连流量为 $1$ 的边,每列向 $T$ 连流量 $1$ 的边就好了。
边数是 $O(n^2)$ 的,显然不能过,考虑扫描线,然后线段树优化建图,叶节点向列连流量为 $1$ 的边,不下传标记,如果这个结点为 $0$,由父亲向他连流量 $∞$ 的边(这条边可能存在很久,不只被用一次),每次在修改区间内的点都需要复制一遍。
这样边数就降为了 $O((n+q)\log n)$ 的,由于很多边流量为 $1$,所以跑得很快,可以过。
重生 / CF1638F
$k=1$ 的话就直接枚举就行了,当然也可以单调栈。
接下来考虑 $k=2$,对于两个区间的关系分讨。
如果两区间相离,则枚举所有区间,在左右端点分别更新,然后分别前缀后缀 $\max$ 就能算了。
以下默认两区间有交,交为 $[l,r]$,$a_h=\min_{i=l}^ra_i$,枚举这个交。
必有一种最优解使得两次操作中有至少一次的 $x$ 等于某个 $a_p(p<l\lor p>r)$。
证明:如果不满足,则一直将短区间 $x$ 减一,长区间 $x$ 加一,在不劣的情况下满足条件。
分类讨论:
- 如果两线段没有包含关系:
- 如果两个区间的 $x$ 分别对应一个 $a_p$:对每个 $a_i$ 预处理出 $sl_i$ 和 $sr_i$ 表示 $x$ 不大于 $a_i$ 时,从 $r$ 向左进行一次操作的最大值和从 $l$ 向右进行一次操作的最大值。枚举第一个 $x=a_i$,双指针搞出最大的第二个 $x=a_j$ 使得 $a_i+a_j\le a_h$,将答案对 $sl_i+sr_j$ 取 $\max$。
- 如果只有一个区间的 $x$ 对应一个 $a_p$:处理出 $fl_i=p$ 为最小的下标 $p$ 使得 $[p,r]$ 都小于 $a_i$,$fr_i$ 同理。枚举 $x=a_i$,则另一个 $x=a_h-a_i$,双指针搞出最小的 $a_j\ge a_h-a_i$,则 $a_j-a_i$ 能延伸的长度也就是 $a_j$ 能延伸的长度。注意 $i<l$ 和 $i>r$ 都要考虑到。
- 如果两区间成包含关系:不妨令第二个区间为 $[l,r]$,枚举 $x_1=a_i$,用 $fl,fr$ 算出能延伸的长度即可。
这样单个 $[l,r]$ 区间能做到 $O(n)$。注意到 $h$ 相同的区间里极长的才有意义,所以枚举 $h$,向左向右求出极长的 $[l,r]$ 就只有 $O(n)$ 个区间了。
时间复杂度 $O(n^2)$,注意实现常数。