「Note」CF 套题
最后一次添加的题目:CF1572C
CF *2000-*2100
\(\color{blueviolet}{CF771C}\)
非常好题目啊。
首先考虑题目让你求的到底是个什么东西,不难看出 \(f(u, v) = \left\lceil\frac{dis(u, v)}{k}\right\rceil = \frac{dis(u, v) + (k - dis(u, v) \mod k)}{k}\),然后这个东西求和可以直接求分子的和然后最后除以 \(k\)。
分子一共有两部分,第一部分是所有路径的长度和,可以用点分治直接求,但第二部分貌似看起来有点困难。考虑到 \(k\) 比较小,所以可以尝试按余数分类,设 \(ans_i\) 为 \(dis(u, v) \equiv i \pmod{k}\),的路径条数,那么第二部分即 \(\sum \limits_{0 \le i < k} ans_i(k - i)\),也就是说第二部分只需要求出路径长度模 \(k\) 为各个余数的路径数量即可,这个东西也可以用点分治维护,每次更新记一个桶,然后用乘法原理计数即可。
\(\color{blueviolet}{CF468B}\)
类似二分图的东西,逻辑是有趣的。
首先考虑数字 \(x\),若 \(a - x\) 已经给出了,那么两者一定同集合。证明是简单的,考虑如果 \(x\) 在集合 \(A\),那么 \(a - x\) 一定在集合 \(A\);如果 \(x\) 不在 \(A\) 内,那么 \(a - x\) 也不能在 \(A\),只能在 \(B\) 内。对于 \(b - x\) 同理,所以可以这样合并 \(x, a - x, b - x\)。
考虑数字 \(x\),若 \(a - x\) 未给出,那么 \(x\) 只能在 \(B\) 内,直接塞进去即可。
这实际上是一个类似二分图的东西,可以用并查集瞎维护,建两个虚点表示集合 \(A, B\),按照上述方式进行合并,最后判断两个虚点是否在一块,如果在一块则无解。
\(\color{blueviolet}{CF855C}\)
DP 是显著的,需要考虑颜色编号的大小关系,所以把当前节点颜色编号关系压进状态 \(f_{i, j, 0/1/2}\),在 \(x\) 子树内已经取了 \(j\) 个特殊颜色,当前节点颜色编号小于/等于/大于 \(k\) 的方案数,转移类似树形背包,讨论是简单的,需要注意初值。
\(\color{royalblue}{CF840B}\)
神秘题,其实很显著,但没切出来。
考虑无解情况,因为无向边只能带来偶数个度数,所以总度数为奇数且无限制为 \(-1\) 的点时无解(因为有 \(-1\) 就可以调整为偶数)。可以证明在总度数为偶数时一定有解:
首先应该注意到总图连通,所以一定存在一颗完整的 DFS 生成树。按以上构造方式一定可以保证处理完之后除根节点外的所有点满足条件。若此时根节点度数不满足限制,那么此时总度数和一定是奇数,这与总度数为偶数是矛盾的,故一定有解。
\(\color{royalblue}{CF455C}\)
没啥水平题。
考虑两棵树连起来一定是将两棵树直径中点连起来,然后直径构成是显然的三部分,直接维护即可。
连通性的话放一个并查集即可。
\(\color{blueviolet}{CF555B}\)
题意转化为给定一些点和区间,一个点可以覆盖至多一个它所在的区间,每个区间至少被一个点覆盖,问是否有覆盖方案。
把区间按照右端点排序,然后在 set 里二分合法最靠左点来覆盖区间,找不到就是无解。
\(\color{royalblue}{CF1343E}\)
简单题,首先考虑不能直接贪心的原因,两段最短路可能有重叠部分,重叠部分有且只有可能是由 \(B\) 出发的一段路径。
考虑枚举中转点 \(D\),使得 \(2dis_{D, B} + dis_{D, A} + dis{D, C}\) 最小,发现做三遍 BFS 即可。
\(\color{blueviolet}{CF827C}\)
好题。
\(1 \le |e| \le 10,|\sum| = 4\),考虑从这几点下手。
首先每个字符可以分开考虑,然后对于每个长度,每个匹配的字符位置开一个树状数组。
本质上是判断同余位置的字符相等个数,也就是对于每种字符,每个模数,每个余数开一个树状数组,总计 \(400\) 个,空间允许。
CF *2200-*2300
\(\color{royalblue}{CF1584E}\)
考虑最左元素最右元素状态是固定的,先只考虑左侧情况。
列出每个元素的第一次变化:
\(\begin{aligned} a_1 \leftarrow 0\\ a_2 \leftarrow a_2- a_1\\ a_3 \leftarrow a_3-( a_2- a_1)\\ a_4 \leftarrow a_4-[ a_3-( a_2- a_1)]\\ \vdots\\ a_n \leftarrow a_n-(\ldots-( a_2- a_1)\ldots) \end{aligned}\)
拆开之后有:
\(\begin{aligned} a_1 \leftarrow 0\\ a_2 \leftarrow a_2- a_1\\ a_3 \leftarrow a_3- a_2+ a_1\\ a_4 \leftarrow a_4- a_3+ a_2- a_1\\ \vdots\\ a_n \leftarrow \begin{cases} a_n- a_{n-1}+\cdots+ a_1 n\equiv1\pmod 2\\ a_n- a_{n-1}+\cdots-a_1 n\equiv 0\pmod 2 \end{cases} \end{aligned}\)
发现是正负交替和,所以有以下限制:
- 整个序列正负交替和等于 \(0\)。
- 每个前缀正负交替和非负。
考虑枚举右端点,维护有多少左端点合法。
因为奇偶正负项不同,可以分开维护。
对于第二个限制,只要每次加入新元素后弹出不合法值即可,第一个只需要找到加入 \(a_r\) 为 \(0\) 的交替和即可,加入 \(a_r\) 即根据奇偶性在两堆数字中都加减 \(a_r\) 即可。
于是需要维护操作:
- 所有数字加一个数。
- 插入一个数。
- 查找等于某数的个数。
- 删除所有大于 \(0\) 或小于 \(0\) 的数。
显然的 map 即可。
\(\color{royalblue}{CF1603C}\)
首先最后一个数字肯定不会被分裂,因为如果其被分裂只会使前面的数字上界减小,显然不优。
贪心地考虑分裂一个数,一定分裂成尽量均匀更优,并且让最小的数最大,举例来说将 \(9\) 分裂为不小于 \(4\) 的数时,\(3, 3, 3\) 优于 \(2, 3, 4\)。
可以知道以下性质:
- \(x\) 分裂为 \(\le v\) 的数字,最少分裂次数为 \(\lceil \frac{x}{v} \rceil - 1\),并分裂为 \(\lceil \frac{x}{v} \rceil\) 个数。
- \(x\) 分裂为 \(t\) 个数字,在最优分裂情况下其中的最小值为 \(\lfloor \frac{x}{t} \rfloor\)。
设 \(f_{i, j}\) 表示从后向前处理完第 \(i\) 个数,最小值为 \(j\) 的序列方案数,先不考虑统计答案。
对于当前的 \(a_i\),限制的上界固定,分裂出的值也固定,考虑每次拿出分裂次数相同的上界 \(l, r\),即当 \(a_i\) 需要分裂为小于 \(x \quad (l \le x \le r)\) 的数时,\(a_i\) 的分裂状态都是相同的。
设其分裂出最小值 \(v\),于是有转移 \(f_{i, v} = \sum \limits_{j = l}^r f_{i + 1, j}\)。
现在考虑统计答案,每次分裂时假设分裂为 \(t\) 个数字,则对答案有 \(i \times (t - 1) \times f_{i, v}\) 的贡献。
边界情况为 \(f_{n, a_n} = 1\)。
其中求和是单调的,可以用什么队列维护,我选择用 vector 记录,然后滚动数组优化一下即可。
\(\color{royalblue}{CF1610E}\)
我们尝试求最长的合法序列长度。
当 \(k= 1\) 或 \(k = 2\) 时都没有毒瘤序列,考虑 \(k = 3\) 时,有序序列的非法情况只有 \(c_1 < \frac{c_1+c_2+c_3}{3} < c_2 \le c_3\),这等价于 \(\frac{c_1+c_2+c_3}{3} < c_2\),即 \(c_1 + c_3 < 2c_2\)。
有结论一个毒瘤序列一定有一个长度为 \(3\) 的序列是毒瘤的,考虑反证法。
现在假设对于一个长度为 \(k\) 毒瘤序列,其中没有长度为 \(3\) 的毒瘤序列。
设 \(m = \lceil \frac{k}{2}\rceil\),对于 \(c_m\),因为序列 \(c\) 毒瘤,所以有 \(c_m\) 严格大于序列平均值。
然后考虑其中没有长度为 \(3\) 的毒瘤序列,所以对于任意 \(i\),满足序列 \(c_i, c_m, c_{k - i + 1}\) 不毒瘤,于是有 \(c_i + c_{k - i + 1} \ge 2c_m\),这个东西在 \(i = m\) 或者 \(k - i + 1 = m\) 时显然也成立。
于是有 \(\sum \limits_{i = 1}^k c_i + c_{k - i + 1} \ge 2k \times c_m\),将这个式子两侧同时除以 \(2k\) 有 \(c_m\le \frac{\sum_{i=1}^k c_i}{k}\),与之前的 \(c_m\) 严格大于序列平均值相冲突。
考虑当序列刚开始只有两个值时 \(a_x, a_y\),我们考虑从大往小加入数字,最开始加入一个数需要保证 \(a_t \le \frac{a_x + a_y}{2}\),下一次再加入一个数需要保证 \(a_t' \le \frac{a_x + a_t}{2}\),这样每次数字的选择范围会减少一半,这样至多选 \(\log\) 个。我们希望最初的的选数范围尽可能大,于是我们考虑枚举最小值 \(a_i\) 并加入 \(a_n\),然后每次加入一个能加入最大的数字,二分即可。
\(\color{royalblue}{CF1542D}\)
考虑对每一个元素 \(x\) 求出有多少字序列使得它产生贡献。
设 \(f_{i, j}\) 表示前 \(i\) 个操作,现在集合内有 \(j\) 个比它小的元素的总子序列数量。
首先对于 \(x_i = x_j\) 我们钦定下标更小的那一个被优先删除,这样可以避免掉重复计算。
先枚举 \(x\) 的位置 \(p\),对于 \(i < p\) 的转移:
-
第 \(i\) 个操作为删除操作,有 \(f_{i, j} = f_{i - 1, j} + f_{i - 1, j + 1} + [j = 0]f_{i - 1, j}\)。
前两项分别是选当前操作、不选当前操作的贡献,最后一项是当集合中没有比 \(x\) 小的元素时删除一个后比 \(x\) 小的元素数量为 \(0\)。
-
若 \(x_i > x\),有 \(f_{i, j} = 2f_{i - 1, j}\)。
-
若 \(x_i < x\)(因为 \(i < p\) 所以我们钦定相等也算当前情况。),有 \(f_{i, j} = f_{i - 1, j} + [j > 0]f_{i - 1, j - 1}\)。
对于 \(i = p\),有 \(f_{i, j} = f_{i - 1, j}\)。
对于 \(i > p\):
-
第 \(i\) 个操作为删除操作,有 \(f_{i, j} = f_{i - 1, j} + f_{i - 1, j + 1}\)。
-
若 \(x_i > x\)(因为 \(i > p\) 所以我们钦定相等也算当前情况。),有 \(f_{i, j} = 2f_{i - 1, j}\)。
-
若 \(x_i < x\),有 \(f_{i, j} = f_{i - 1, j} + [j > 0]f_{i - 1, j - 1}\)。
初值为 \(f_{0, 0} = 0\),统计答案即值乘以方案数即可。
\(\color{blueviolet}{CF1559E}\)
平凡题。
先考虑前两个限制条件,背包是显著的,设 \(f_{i, j}\) 表示前 \(i\) 个数字,和为 \(j\) 的方案数,转移可以暴力枚举 \(a_i\) 取值,这个显然可以用前缀和优化到 \(O(nm)\)。
考虑枚举 \(g = \gcd(a_1, \dots, a_n)\),我们在 DP 时保证所有数字填的时候是 \(g\) 的倍数,设 \(f_{i, j}\) 表示对于当前枚举的 \(g\),处理前 \(i\) 个数字,和不超过 \(j \times g\) 的方案数。初值状态为 \(f_{0, 0} = 1\), 目标状态为 \(f_{n, m / g}\),我们发现最终并不能保证 \(\gcd\) 为 \(g\),只能保证 \(\gcd\) 为 \(g\) 的倍数,考虑容斥。设 \(ans_i\) 表示 \(\gcd\) 恰好为 \(g\) 的方案数,\(f_{n, m / g}\) 是已经求好的 \(\gcd\) 为 \(g\) 倍数的所有方案,有 \(ans_g = f_{n, m / g} - \sum\limits_{g | i\land g \not= i} ans_i\)。
所以倒序求即可,复杂度 \(O(nm\ln m)\)。
\(\color{royalblue}{CF1575H}\)
数据范围提示我们用 \(O(n^3)\) 的算法来解决,这种匹配问题可以考虑放到 ACAM 或者 KMPAM 上,后者本质上是只添加一个字符串的前者。
很明显我们可以把串 \(b\) 的 KMPAM 处理出来在上面跑 DP,具体地讲,需要处理出一个 \(to_{i, j}\) 表示匹配到 \(b\) 的 KMPAM 的状态 \(i\) 时,下一个字符为 \(j\) 时,应该转移到的状态。
当 \(j = b_{i +1}\) 时,有 \(to_{i, j} = i + 1\),否则有 \(to_{i, j} = to_{nex_i, j}\)。
具体求法可以参考 ACAM 求 fail 的过程,我写 KMP 的版本的时候写挂了,所以干脆换成 ACAM 的处理方式处理出了 \(to\) 数组。
接下来考虑 DP,设 \(f_{i, j, k}\) 表示 \(a\) 匹配到第 \(i\) 个字符,当前在 \(b\) 的 \(j\) 状态下,\(b\) 已经完全匹配过 \(k\) 次的最小代价。
我很难知道有哪些 \(to_{p, q} = j\) 所以填表法在第二维上是困难的,所以第二维用刷表法处理,另外第一维是线性的,第三维刷表填表都是可行的,因为只与 \([to_{j, ch} = m]\) 的值有关(\(ch\) 是枚举的 \(a_i\))。
每次 \(f_{i, to_{j, ch}, k +[to_{j, ch} = m]} \leftarrow \min\{f_{i, to_{j, ch}, k +[to_{j, ch} = m]}, f_{i - 1, j, k} + [a_i \not= ch]\}\) 即可。
\(\color{blueviolet}{CF1156F}\)
DP 状态是显然的,设 \(f_{i, j}\) 表示第 \(i\) 次抽卡抽取到 \(j\) 的概率,有转移:
\(f_{i, j} = \sum \limits_{k = 0}^{j - 1} f_{i - 1, k} \times \frac{buc_j}{n - i + 1}\)
这个东西后面的系数显然可以提出来然后前缀和优化转移。
然后考虑统计答案,每次转移的时候记录一个下一次抽取和这一次抽到一样的概率累加到答案上即可。
\(\color{blueviolet}{CF429C}\)
按子树大小从大到小枚举合法父亲进行搜索,复杂度是阶乘级别,无法接受。
发现子树大小为 \(1\) 的节点父亲是谁都无所谓,所以不用枚举,并且根据题目中“非叶子节点子节点个数至少为 \(2\)”这条性质可以得到叶子节点个数超过一半,复杂度降为 \(\left\lfloor \frac{n}{2} \right\rfloor !\),可以接受。
\(\color{blueviolet}{CF1097D}\)
设 \(f_{k, i}\) 表示对 \(i\) 操作 \(k\) 次后的期望值,考虑列出其所有因数进行求解式子是显著的。
发现这个东西是积性的,即 \(f_{k, a /times b} = f_{k, a} \times f_{k, b} \quad(\gcd(a, b) = 1)\),推导是简单的。
然后考虑对于每个质因子做一遍 DP,记忆化下来可过。
\(\color{blueviolet}{CF678E}\)
看到题目范围不难想到状压,每次转移时需要知道当前赢家是谁,所以打进状态,设 \(f_{i, j}\),表示状态 \(i\) 中的人都已经决斗过了,其中 \(j\) 是目前的赢家的概率,每次考虑加入一个新人进行决斗,转移是简单的。
\(\color{royalblue}{CF476E}\)
考虑删除一些位一定是为了匹配成一个串,否则杂乱的删除一定不优。
设 \(g_i\) 表示以 \(s_i\) 为开始字符要向后匹配到哪里可以出现一个完整的串 \(p\)。(可以不连续的,在 DP 过程中考虑删除其中的无用字符。)
设 \(f_{i, j}\) 表示当前匹配到串 \(s\) 的第 \(i\) 位,删除了 \(j\) 个字符最多能匹配完成的次数。
转移是简单的,要么继承之间的值,要么从当前位向后寻找一个串完成匹配。
CF *2400-*2500
\(\color{blueviolet}{CF1795F}\)
二分这个操作次数,然后处理出来每个人需要走多少步,贪心地向下走,找向下深度最大的能走的位置,如果向下不够就尝试把贡献转移到父节点,前提是父节点是合法点,DFS 判断即可。
\(\color{blueviolet}{CF1101F}\)
用到了一个奇妙 Trick。
对于每辆车可以考虑二分油箱容量,进行贪心验证,每次不能走了就加油,最后判断加油次数是否小于限制即可。
如果暴力二分是 \(nm\log V\) 的,不太能接受,发现其中有一些答案是无用的,比如前 \(i - 1\) 辆卡车的答案为 \(ans\),第 \(i\) 辆卡车在 \(ans\) 的情况下合法,我们就无需计算 \(i\) 的答案。
这样有了一些小剪枝,但发现当答案单调上升的时候复杂度仍然会卡到上界,考虑随机化优化一下。
有如下结论:对于长度为 \(n\) 的随机序列,前缀最大值的个数为 \(O(\log n)\)。
证明是简单的。对于一个排名为 \(x\) 的数字,需要保证所有比它大的数字都要出现在其后面,则其为一个前缀最大值。我们将排名依次为 \(x, x + 1, \dots , n\) 的数字作为一个子序列拿出来,\(x\) 为前缀最大值的概率等价为 \(x\) 在这个子序列中是第一个数的概率,所以有其概率为 \(\frac{1}{n - x + 1}\)。期望个数即 \(\frac{1}{1} + \frac{1}{2} + \dots + \frac{1}{n}\),积分后可以得到是 \(O(\log n)\) 的。
所以我们对于每辆卡车随机赋权值,并按照权值排序,这样得到的前缀答案最大值期望个数为 \(O(\log m)\),所以总期望复杂度为 \(O(n \log m \log V + m\log V)\),可以接受。
\(\color{blueviolet}{CF121E}\)
看题解之后选择了一种较为优异的写法。
树状数组维护每个位置是否是合法数字,区间修改直接暴力修改,发现此处的值贡献有变再用树状数组进行修改,枚举的复杂度是巨大的,但考虑到每个数递增,并且合法数字数量不多,所以修改次数是少量的,总复杂度大概 \(10^9\) 出头,常数很小,跑得飞快。
\(\color{blueviolet}{CF847J}\)
考虑网络流建模,二分最大送礼物数量作为每个人的总容量,对于每一个限制(一条边),连两个人到其的边,并连向汇点。
能流满即存在合法方案,输出方案考虑哪条边流满了即可。
\(\color{blueviolet}{CF962F}\)
考虑在 DFS 生成树上乱搞。
首先考虑非树边(即返祖边),当它覆盖到的所有树边都只被覆盖一次(只被它覆盖),那么此非树边合法。
对于树边,当它只被非树边覆盖一次,并且此非树边合法,此树边合法。
考虑树上差分处理覆盖次数,然后找合法非树边,暴力判断是否合法,若合法再将其覆盖到的树边标记为合法即可。
\(\color{blueviolet}{CF1334F}\)
没看懂 \(O(n \log n)\) 写法,写的 \(O(n)\) 的。
为了方便处理边界,在 \(a, b\) 两序列前后分别加上 \(0, n + 1\),下标从 \(0\) 开始。
考虑给 \(a\) 重新赋值:
- \(a_i = b_j\),则使 \(a_i \leftarrow 2j\)。
- \(b_j < a_i < b_{j + 1}\),则使 \(a_i \leftarrow 2j + 1\)。
题意转化为保留一个 \(0, 2, 4, \ldots 2m\) 的序列,在第一个 \(2i\) 出现之前不能出现 \(2i - 1\),简单思考后可以发现此限制与原限制等价,然后就可以考虑 DP 了。
设 \(f_i\) 表示到 \(i\) 为止,只考虑权值不超过 \(2j\) 的贡献的最小花费,其中需要保证 \(a_i = 2j\)。
首先考虑强制 \(a_i\) 作为第一个 \(2j\) 出现,有:
\(f_i=\{f_x+\sum_{k=x+1}^{i-1}[p_k<0]p_k\}+\sum_{k=0}^{i-1}[a_k=2j\lor a_k=2j-1][p_k>0]p_k\)
其中 \(a_x = 2j - 2\),我们只需要从最近的 \(2j - 2\) 转移过来即可。
对于不考虑取第一个的话有转移:
\(f_i=\{f_x+\sum_{k=x+1}^{i} [p_k<0]p_k\}\)
代码是简单的,随便写写即可。
\(\color{blueviolet}{CF626F}\)
神秘的 DP 题。
首先不难想到的是把 \(a\) 排序,分组时只需要考虑最小值,因为每次加入一个数一定是最大值。
设 DP 式 \(f_{i, j, k}\) 表示处理到第 \(i\) 个数,目前有 \(j\) 个未封闭的组,总不和谐度之和为 \(k\) 的方案数。
考虑第 \(i\) 个数的放置情况:
-
加入某个组,保持此组仍为开放。
-
加入某个组,封闭此组。
-
新建某个组,开放此组。
-
新建一个组,封闭此组。
对于新建一个组需要转移负贡献,也就是 \(k \leftarrow k - a_i\),封闭一个组需要加入当前贡献 \(k \leftarrow k + a_i\)。
转移是简单的,但此方法复杂度较高,而且第三维会出现负数,比较难处理。
尝试给出一种较为好理解优化的方式。把每个组想象成一条正在延伸的线段(若已封闭那么这条线段不会延伸),左端点是组内最小值,右端点是最大值,考虑加入一个 \(a_i\),那么未封闭的所有组最大值至少为 \(a_{i + 1}\),也就是有 \(k \leftarrow k +j \times (a_{i + 1} - a_i)\),相当于所有未封闭线段右端点右移一段距离。
考虑把贡献都变成差分的形式,第三维没了负数,并且值域变小,转移随便写写即可,时间复杂度 \(O(n ^ 2 \max\{k, \max\{a_i\}\})\)。
\(\color{blueviolet}{CF825F}\)
考虑 DP,分段 DP 是显著的,考虑设 \(f_i\) 表示以 \(i\) 结尾的前缀的压缩最小长度。
转移时考虑枚举断点进行转移。
不难得出一个结论:对于一个串来说肯定找到最小循环节压缩是最优的,证明是简单的。
于是问题转化为如何 \(O(1)\) 找一个子串的最小循环节,这时候用到一个结论,对于一个长度为 \(n\) 的串,其最短循环节为 \(n - nex_n\)(其中 \(nex_i\) 是 KMP 中求的 border,并且当且仅当此值能整除串长时成立),于是可以 \(O(n^2)\) 预处理每个后缀的 border,剩下的都是平凡的。
\(\color{royalblue}{CF449D}\)
首先考虑总方案数减去不合法方案数,枚举 \(1\) 的个数进行容斥。
于是需要求 \(val_{st}\) 表示包含状态 \(st\) 的数一共有多少个。
现在设状态 \(a \supsetneq b \supsetneq c\),并且 \(a\) 状态比 \(b\) 状态在 \(x\) 位上多 \(1\),\(b\) 比 \(c\) 在 \(y\) 位上多 \(1\)。
考虑 \(a\) 的贡献加到 \(c\) 上的方式,先去掉 \(x\) 和先去掉 \(y\) 的贡献路径是等价的,所以我们钦定先去掉较小的位,这样不会重复。
\(\color{blueviolet}{CF543C}\)
状压是显著的,设 \(f_i\) 表示达到状态 \(i\) 时的最小花费,其中状态表示每一个字符串是否存在一位不同。
考虑对于一个 \(f_i\) 进行向下转移,找到第一个不合法字符串 \(now\),有两种转移方式,第一种是改这个字符串使得其合法,第二种是改一群某位相同的字符串,使得这一群字符串合法。
第一种转移是显然的,第二种考虑预处理一个 \(g_{i, j}\) 表示将第 \(j\) 位与第 \(i\) 个字符串相等的一群字符串都改合法的方案,显然是不改花费最大的那个,预处理是简单的。
\(\color{blueviolet}{CF639D}\)
有点质量的题。
将 \(v\) 进行排序是显然的。
首先只考虑加一的操作,枚举最终达到的值 \(v_i\),对于排好序的 \(v\) 序列,越靠后的数字花费越少,所以最终一定选择的是 \(v_{i - k +1}\) 至 \(v_i\)。如果只是这样我们可以直接拿前缀和算,但是其不足以扩展出此题正解,我们考虑劣化整个计算过程。
依然固定最终值 \(v_i\),考虑用队列维护选择的元素,在维护过程中加入一个元素,如果目前已经有 \(k\) 个元素且这个元素的花费比最大花费要小,那么我们此时去掉最大花费加入此元素一定更优。因为上文提到的花费单调性,所以此时队首一定是最大花费元素,直接弹出队首即可。
当存在加五操作时,花费单调性将不对整个序列存在(比如上一个元素可以通过加五到达目标值,而当前元素只能通过加一操作达到,此时当前花费可能更大。),因此不能直接用队列维护。考虑到将所有余数相同的数拿出来之后仍然具有单调性,所以可以按照余数分类(对 \(5\) 取模),对于每个余数做一个队列,所有队列中元素总个数不超过 \(k\),每次尝试从所有队首弹出最大的进行决策。
再考虑加五操作的另一种影响,目标值可能不一定是 \(v_i\),也可能是 \(v_i + val \quad (0 \le val < 5)\),所以都枚举一遍进行计算即可,带有五倍常数,去掉重复枚举可以减小常数。
注意如果 \(b > 5c\) 时 \(b \leftarrow 5c\)。
\(\color{blueviolet}{CF1753D}\)
很好的题,注意到一个结论,一个块最多只会被移动一格(保证移动后一定跟原来位置有交)。
于是可以看做在途中移动一个方格,设 \(f_i\) 表示将某个空位移动到格子 \(i\) 的最小代价,答案即两个相邻位置的代价和。
其实看似这个 DP 会有一些重复和疏漏,其实正确性是可以证明的,非常巧妙,可惜题解里没人提到这些。(哈哈我也不写!)
CF *2600-*2700
\(\color{blueviolet}{CF67C}\)
挺好玩的性质题。
DP状态是显然的,\(f_{i, j}\) 表示 \(a\) 串匹配前 \(i\) 个字符,\(b\) 串匹配前 \(j\) 个字符的最小代价。
前三个操作的转移是显著的,考虑第四个操作以及其代价限制起什么作用。
连续的交换不如添加和删除,唯一可以起到的作用是交换两个数,可以考虑删除中间一段,交换两头的字符,再添加中间的一段。
具体的来讲,假设现在正在处理 \(a_i, b_j\),设 \(b_j\) 最后一次出现在 \(a_1 \sim a_i\) 中的 \(x\) 位置,\(a_i\) 出现在 \(b_1 \sim b_j\) 的 \(y\) 位置,则我们先令 \(a_1 \sim a_{x - 1}\) 与 \(b_1 \sim b_{y - 1}\) 匹配好,然后删除 \(a_{x + 1} \sim a_{i - 1}\),交换后再添加 \(b_{y + 1} \sim b_{j - 1}\),转移是简单的。
\(\color{blueviolet}{CF1542E2}\)
非常有水平的题。
先枚举相同前缀长度,然后钦定下一位不同,于是问题转化为对于每个 \(i\) 求 \(i\) 阶排列对 \((p, q)\) 的数量,使得 \(p_1 < q_1\) 且 \(\pi(p) > \pi(q)\)。其中 \(\pi(x)\) 为序列 \(x\) 的逆序对数。
设 \(f_{i, j}\) 表示 \(i\) 阶排列 \(\pi(p) - \pi(q) = j\)。转移考虑枚举开头元素 \(p_1, p_2\) 有:
\(f_{i, j} = \sum\limits_{p_1 = 1} ^ {i} \sum\limits_{q_1 = 1} ^ i f_{i - 1, j - p_1 + q_1}\)
值得注意的是下标可能为负,所以做的时候要整体位移一段。
答案即:
\(\sum\limits_{p_1 = 1} ^ i \sum\limits_{q_1 = p_1 + 1} ^ i f_{i - 1, j - p_1 + q_1}\)
发现只关心开头元素差值,考虑枚举差值 \(d = p_1 - q_1\),则有:
\(f_{i, j} = \sum\limits_{|d| < i} f_{i - 1, j - d} (i - |d|)\)
把 \(d\) 按正负分开:
\(f_{i, j} = \sum\limits_{d = 1} ^ {i} f_{i - 1, j + d} (i - d) + \sum\limits_{d = 0} ^ {i - 1} f_{i - 1, j - d} (i - d)\)
把前半部分拿出来做以下推导:
\(\sum\limits_{d = 1} ^ {i} i f_{i - 1, j + d} - \sum\limits_{d = 1} ^ {i} d f_{i - 1, j + d}\)
\(\sum\limits_{d = 1} ^ {i} (i + j) f_{i - 1, j + d} - \sum\limits_{d = 1} ^ {i} (j + d) f_{i - 1, j + d}\)
然后发现关于第二维做两种前缀和即可,后半部分类似。
\(\color{blueviolet}{CF578D}\)
考虑转化题意,将原字符串去掉一个字符,在任意一个位置添加一个字符,问能通过这样得到多少个不同的字符串。
考虑直接计数所有情况,并去掉重复贡献。枚举原字符串去掉的字符(相同连续段只枚举一次),添加任意一个字符的方案为 \(nm\),其中 \(m\) 是字符集大小。
第一种重复情况,假设去掉一个字符后串中有一个字符 a
那么在其左右两侧添加一个字符 a
的效果相同,这样的重复总共有 \(n - 1\) 种,所以答案减去 \(n - 1\)。
第二种重复情况,假设原字符串的一个子串 ab
,去掉 a
在 b
后添加 a
的效果,与去掉 b
在 a
前添加 b
效果相同。这种重复存在于所有不同的相邻字符之间,考虑对于枚举的每个不是字符串首位的字符答案都减去 \(2\)。
第三种重复情况,对于一种 \(\{a, str, b\}\) 的情况(\(a, b\) 为字符,\(str\) 为一段字符串),我们经过变换可以得到 \(\{b, a, str\}, \{str, b, a\}\) 两种排列,当 \(str\) 是由 \(b, a\) 交替组成的循环节为 \(2\) 的字符串时会出现重复。所以对于 \(\{a, b, \dots, a, b\}\) 的这种极长连续段考虑减去其所有子串。对于这个有巧妙的方式解决,设 \(cnt\) 为连续的 \(s_{i - 1} = s_{i + 1}\) 个数,其中 \(i\) 是正在枚举的位置,不能是起始或终止位置,每次将答案减去 \(cnt\) 即可。
\(\color{blueviolet}{CF1572C}\)
去个重先,连续段都缩到一起。
区间的状态是明显的,设 \(f_{i, j}\) 表示区间 \([i, j]\) 内颜色都变成 \(c_j\) 的最小代价。\(n^3\) DP 是显著的,每次枚举中转点 \(k\),拼凑 \(f_{i, k}, f_{k +1, j}\)。
发现当 \(c_k \not = c_j\) 时,这种转移一定可以由下面这么转移替代:
\(f_{i, j} = \min\{f_{i, j - 1} + 1, f_{i + 1, j}\}\)
于是只要特殊考虑 \(c_k = c_j\) 的情况即可,记录个前驱简单枚举即可。
\(\color{blueviolet}{CF494C}\)
区间不会交错,使得可以根据区间包含关系建出一颗森林,我们添加一组 \(l = 1, r = n, p = 0\) 的修改,可以保证是一棵树,考虑 DP。
设 \(f_{i, j}\) 表示 \(i\) 子树内,最大值为 \(j\) 的概率,但这样并不好转移,考虑改变状态,有 \(f_{i, j}\) 表示 \(i\) 子树内,最大值不超过 \(j\) 的概率,这样转移是简单的,考虑当前节点是否成功修改即可。
第二维状态仍然很大,但其中有很多无用状态,考虑剪枝。对于一个节点 \(i\),设操作前最大值为 \(mxv_i\),那么操作后最大值的范围是 \([mxv_i, mxv_i + q]\),所以再次改变状态,设 \(f_{i, j}\) 表示第 \(i\) 子树内,最大值不超过 \(mxv_i + j\) 的概率,转移的时候作差削除差异即可。
\(\color{blueviolet}{CF883B}\)
比较平凡的题目。
先正向反向求出每个节点的权值上下界,然后贪心求解线段覆盖之类的方案即可。
\(\color{blueviolet}{CF487D}\)
考虑将 \(n\) 分块维护,设 \(to_{x, y}\) 表示从 \((x, y)\) 出发走到的第一个块外位置,特别的,如果从此点出发会停止在此块内那么就记为答案。
修改的时候就整块重构,这里加个剪枝从修改的位置开始,因为只会向下影响,跑得飞快。
询问是简单的,一直跳坐标直到不能跳为止。
\(\color{blueviolet}{CF1473F}\)
此题是坏题,他卡你空间。
每一个元素有选或不选两种状态,并且有依赖项,元素的贡献有正负,数据范围不大,可以自然联系到最大权闭合子图,采用最小割模型。
建模方式如下:
- 对于一个正权点 \(u\),连边 \(S \to u\),容量为 \(b_i\)。
- 对于一个负权点 \(u\),连边 \(u \to T\),容量为 \(-b_i\)。
- 对于所有 \(i\),对于其所有依赖的 \(j\) 连边,容量为正无穷。
但这样建边空间就爆炸了,考虑到值域很小,一个数不同约数个数不会很多。对于一个数 \(a_i\),枚举其约数 \(x\),对于每一个 \(x\) 只需要向最近的 \(x\) 建边即可,这样由于依赖关系的传递性不会出问题。
现在考虑最小割的意义,对于源点到正权点的一条边流满表示这个点我们舍弃掉了,对于负权点到汇点的边流满表示这个点我们被迫选择了,所以有答案 \(\left( \sum \limits _ {b_i > 0} b_i \right) - f\),其中 \(f\) 为最小割。
\(\color{blueviolet}{CF1511F}\)
此题是神仙题。
先建 Trie 树,设 \(f_{i, u, v}\) 到第 \(i\) 个字符,两个分割分别处在 \(u\) 节点与 \(v\) 节点的方案数。
暴力转移是简单的,数据范围提醒我们要用矩阵优化,对于一个状态(有序数对)\((u, v)\) 建立一个点,若状态 \((u, v)\) 可以向 \((u', v')\) 转移,则在代表两个状态的点之间连边。
特殊地,若 \(u'\) 是终止节点,则 \((u', v')\) 同时具有 \((0, v')\) 的转移,\(v'\) 也同理;若 \(u', v'\) 都是终止节点,状态 \((u', v')\) 同时具有 \((0, 0)\) 的转移。
所以对于上述情况,\((u, v)\) 也可以向 \((u', v')\) 的等价状态连一条边,于是我们得到了一个有向图,等价于让我们求长度为 \(m\) 的从 \((0, 0)\) 到 \((0, 0)\) 路径条数,但此时状态数是 \(1600\) 左右的,显然我们不能接受,考虑优化方式。
首先对于状态 \(u, v\) 它可能是不存在的,因为 \(u, v\) 在 Trie 树上的形态必然是祖先和子代的关系,状态数来到 \(320\) 左右,再考虑 \((u, v)\) 和 \((v, u)\) 在上述图中是对称的存在,考虑在矩阵中所成一个状态即可。
\(\color{blueviolet}{CF1511G}\)
此题是神仙题。
首先转化问题,对于一个询问只要判断 \(\bigoplus \limits _{l \le c_i \le r} c_i - l\) 是否等于 \(0\) 即可。
设 \(f_{i, j}\) 表示 \(\bigoplus \limits _{i \le c_i \le i + 2 ^ j - 1} c_i - i\),考虑如何倍增转移。
\(f_{i, j}\) 由 \(f_{i, j - 1}\) 与 \(f_{i + 2 ^ {j - 1} - 1, j - 1}\) 两部分组成,前者的异或和可以直接转移过来,后者包括的元素每个会与需要的值相差 \(2 ^ {j - 1}\),所以需要额外异或上后者元素个数个 \(2 ^ {j - 1}\),只需要通前缀和维护一下区间元素个数即可。
求答案也是类似的,倍增逼近即可。
\(\color{royalblue}{CF1515G}\)
此题是好题。
首先因为要求了起点终点相同,我们只能在强连通分量中进行求解。
考虑对于一个长度为 \(len\) 的环,我们可以走一圈取得 \(len\) 的贡献,也可以走 \(t - 1\) 次取得 \(-len\) 的贡献,这是显然的。
再考虑对于两个相邻的环,我们可以同时取到两者任意多次,构造是显然的。
所以对于多个环来说,对于每一个环的贡献可以取任意次数(负数也是可行的)。
也就是说对于一个强连通分量,设其中所有环长度为 \(len_i\),再设 \(g = \gcd(len_1, len_2, \ldots, len_cnt)\)。根据裴蜀定理只要判断 \(s = ag - bt\) 的正整数解是否存在即可,再用一次裴蜀定理可以只需判断 \(\gcd(g, t) \mid s\) 是否成立即可。
\(\color{blueviolet}{CF1469F}\)
此题是平凡题。
贪心地考虑加入一条链时,一定是让其中点连向树上的点,并且连到树上的点深度尽可能小。
更加贪心地考虑,先加入长链是更优的(这你还要我证明?)。
现在加链的策略已经固定了,考虑维护信息。
设我们连接的书上的点深度为 \(x\),链长为 \(l\),那么加入这条链产生以下影响:
- 深度为 \(x\) 的白点减少 \(1\)。
- 深度在 \(\left( x + 1, x +\lfloor{ \frac{l - 1}{2}\rfloor}\right]\) 内的白点增加 \(1\)。
- 深度在 \(\left( x + 1, x + (l - 1 -\lfloor{ \frac{l - 1}{2}\rfloor})\right]\) 内的白点增加 \(1\)。
及其显著地,用权值线段树维护,空间开大点即可。
\(\color{blueviolet}{CF1495D}\)
此题是神仙题。
考虑对于 \(x\) 和 \(y\) 共同的生成树一定包含两者的最短路径。
先假设 \(x, y\) 最短路径有且只有一条,考虑其上一点 \(z\),\(x, y\) 两者中一者到其最短路径依然有且只有一条,为了满足 \(dis(x, z), dis(y, z)\) 不变,必须保留此最短路。
当 \(x, y\) 最短路径不止一条时,对于这两条路径上的点依然需要满足上述 \(z\) 的条件,因此多条最短路都需要保留,此时一定会成环,无法保持树的形态,也就一定无解。
现在对于 \(x, y\) 两点已有一条唯一的链链接,考虑其他点如何挂在树上。对于一个点 \(u\) 有边 \((u, v)\),若保留此边(使得 \(v\) 为 \(u\) 的父节点)必须满足 \(dis(x, v) + 1 = dis(x, u) \land dis(y, v) + 1 = dis(y, u)\)。所以我们对于一个点找出其合法父节点个数,对所有的点乘法原理计数即可。
\(\color{blueviolet}{CF1510B}\)
此题是坏题,它让你输出方案
首先考虑转化问题,进行简单图论建模,每个状态向可以达到的状态连边,于是得到一张 DAG,设每个状态点权为其 \(1\) 的数量。
现在问题转化为对于当前 DAG 选出一些路径进行覆盖,一条路径的贡献是其终点权值加一,总贡献是所有路径贡献加和减一(最后一次不需要重置)。
首先考虑最劣情况,对于每一个点单独成为一条路径进行覆盖。每一个点可以选择一个出边把自己贡献抵消掉,这个就类似二分图最大匹配,费用流即可。
建模(设 \((u, v, w, c)\) 表示一条从 \(u\) 到 \(v\),容量为 \(w\),费用为 \(c\) 的边。用 \(u \to v\) 表示原图中的一条边,一个点的\(1\) 的数量设为 \(val_i\)。并设 \(id_i\) 表示 \(i\) 的入点,\(id'_i\) 表示 \(i\) 的出点。):
- 对于所有的 \(i\) 连边 \((S, id_i, 1, val_i), (id'_i, T, 1, 1)\)。(到源点费用为 \(1\) 是因为要加上重置一次。)
- 对于 \(u \to v\),建边 \((id_u, id'_v, 1, -val_u)\)。
\(\color{blueviolet}{CF1523E}\)
此题是好题。
从期望定义入手进行推导。
\(\begin{aligned} E(x) & = \sum \limits_{i = 1}^n P(x = i) \times i\\ & = \sum \limits_{i = 1}^n P(x = i) \times \sum \limits_{j = 0}^{i - 1} 1 \\ & = \sum \limits_{i = 1}^n \sum \limits_{1 \le j \le i} P(x = i) \\ & = \sum \limits_{j = 1}^n\sum \limits_{j \le i} P(x = i) \\ & = \sum \limits_{j = 1}^n P(x \ge j)\end{aligned}\)
现在考虑求 \(P(x \ge j)\),意义上理解这是在操作进行到第 \(j\) 轮时还没停止的概率,也可以理解为已经点亮 \(j - 1\) 盏灯后依然未停止的概率。
先钦定 \(j - 1\) 盏灯是点亮的,再向其中 \(j - 2\) 个空位中每个放入 \(k - 1\) 个暗灯。放完暗灯还有 \(n - (k - 1) \times (j - 2)\) 个位置,在其中选择 \(j - 1\) 个亮灯可以得到合法方案数,再除以总方案数即可。
对其求和即可。
\(\color{blueviolet}{CF1530F}\)
此题是神秘题。
考虑反着做,将至少有一行或一列或一条对角线全为 \(1\) 概率转换为所有行列对角线都至少有一个 \(0\)。
先不考虑行与对角线,只考虑满足所有列都至少有一个 \(0\) 该怎么做,为了使得我们的不完全做法有扩展性,我们考虑使用容斥。
过程如下:
-
加上至少有 \(0\) 列全为 \(1\) 的概率。(对于至少有 \(x\) 列全为 \(1\) 的概率,可以理解为我们选定 \(x\) 列,使得其全为 \(1\)(概率相乘),其他列的 \(0/1\) 情况我们不考虑(概率为 \(1\))。而选定的 \(x\) 列的所有情况概率要加和,比如我选定 \(1\) 列,那么情况总数有 \(n\) 种,这些情况的概率都要加和。)
-
减去至少有 \(2\) 列全为 \(1\) 的概率。
-
加上至少有 \(3\) 列全为 \(1\) 的概率。
-
以此类推。
这样容斥并不难理解,我们需要求的是所有列至少有一个 \(0\) 的情况,对于第一步加的概率显然是全情况的概率,我们减去其中有一列为 \(1\) 的概率,但此时对于两行为 \(1\) 的情况我们减了两遍。举个例子,对于 \(1,2\) 号列全为 \(1\) 的某种情况,我们选定 \(1\) 号列时和选定 \(2\) 好列时分别减去了一遍,所以要在接下来的运算中将其加回来,以此类推。
接下来考虑在这样计算列的贡献时计算行的贡献,首先每一行的贡献互不影响,考虑固定选定的列进行某一行的运算,我只要保证舍去行的全为 \(1\) 的概率即可。我们设 \(f_{i,j}\) 表示对于第 \(i\) 行,选定 \(j\) 状态列(\(j\) 是一个状压状态,这里选定其中的列就相当于在第 \(i\) 行中该位置一定为 \(1\)。),不考虑其他位置 \(0/1\) 状态的概率。这个东西显然是可以预处理的。
于是就有第 \(i\) 行在状态 \(j\) 下的贡献概率 \(g_{i, j} - g_{i, 2 ^ {n - 1}}\),其中我们减掉的是此行全为 \(1\) 的状态,也就是上文说到舍去的部分
最后对角线与列的处理相同,枚举一下状态即可,使得一行与对角线交点的位置为 \(1\) 即可。
\(\color{blueviolet}{CF1539F}\)
这道题是巨大喷流题。
我们只考虑 \(a_i\) 大于中位数的情况,另一情况可以通过取负反转数组取到相同情况,式子只有一个加减 \(1\) 不同。
区间固定时贡献是 \(\frac{t_l + t_m + t_r}{2} - t_r = \left \lfloor \frac{t_l + t_m - t_r}{2} \right \rfloor\)。
其中 \(t_l, t_m, t_r\) 分别表示小于、等于、大于 \(a_i\) 的 数字个数。
然后运用到一个套路,对于这种中位数的东西离线并从小到大遍历数字,比自己小的设为 \(-1\),比自己大的设为 \(1\),求一下以 \(i\) 结尾的后缀最大、以其开头的前缀最大,求和即可。
\(\color{blueviolet}{CF838D}\)
更加神仙的题!
考虑所有情况中合法的概率,假设每个人随机指定位置随机走,将 \(1 \sim n + 1\) 连成环,其中 \(n + 1\) 是增加的位置,此位置是起点,若绕一圈并占据了此节点说明此方案不合法。
结论是所有位置等价,所以占据 \(n + 1\) 的概率为 \(\frac{m}{n + 1}\),合法概率即 \(\frac{n + 1 - m}{n + 1}\),乘以总方案数 \(2 ^ m (n + 1) ^ m\) 即答案。
结论不知道怎么证明,但感性理解挺正确的。
CF *2800-*2900
\(\color{blueviolet}{CF1578K}\)
让你输出方案,所以是大便题。
入手:
\(k = 0\) 时,显然答案为 \(p\),从每个集合里任意选择一个即可构造出方案。
我们定义特殊点对 \((u, v)\),两者之间存在边(不同集合)为“删边”,不存在边(同一集合)为“加边”。
\(2^k\) 看起来像一个比较可行的复杂度,考虑枚举每个删边或者加边的两种状态,我们优先钦定所有删边的状态,然后才到加边。
对于一条删边,其两端点不可能同时存在于答案中,考虑枚举删去哪一个(使得其不可能在答案中)。
对于一条加边,其产生贡献当且仅当本身被选中,并且处于的集合内选择的加边组成了一个团,所以可以枚举此加边是否选中。
答案的计算:
现在考虑每个特殊点对的状态已经确定,如何统计答案。设 \(sum\) 为所有集合内选中的完全图点数总和,\(eptcnt\) 表示集合内部所有点都被删除的集合数量,\(cplcnt\) 表示集合内部选出完全图的集合数量。
集合贡献分为以下三种:
- 删除完的集合无法造成贡献。
- 选出的完全图造成总共 \(sum\) 的贡献。
- 不是以上两种,则每个可以选出任意一个未被删除的点,造成 \(1\) 的贡献。
有答案为 \(sum + p - eptcnt - cplcnt\)。
贡献的计算:
我们期望 \(O(1)\) 统计答案,考虑如何在枚举状态时维护上述变量。
对于一个点,维护 \(avis_i, dvis_i\),分别表示被选中的加边覆盖的次数、被删边删除的次数。这两者只有从 \(0/1\) 之间转换时会造成贡献,但仍需要计数来保证正确性。
对于一个集合,维护 \(acnt_i, dcnt_i, ecnt_i\),分别表示集合内被选中的点数、被删除的点数、被选中的边数。当 \(dcnt_i = siz_i\) 时,会对 \(eptcnt\) 造成贡献;当 \(\frac{dcnt_i\times(dcnt_i - 1)}{2} = ecnt_i\) 时,内部选中了一个合法团,会对 \(sum\) 以及 \(cplcnt\) 造成贡献。
每次维护只要考虑好变量更改顺序,以及贡献的判定,回溯时删除贡献即可。
方案的输出:
假设我们已经知道最优答案以及当时的状态,考虑输出方案。
我们需要重新维护出 \(dvis_i, acnt_i, ecnt_i\) 来判断每一个点是否被加入,我们只要判断此点符合“答案的计算”中三中贡献的哪一点即可。
考虑点 \(i\),设 \(t = s_i\):
- 第一种有 \(dvis_i \not= 0\),不输出。
- 第二种在不满足第一种的情况下,有 \(\frac{dcnt_t\times(dcnt_t - 1)}{2} = ecnt_t\),输出。
- 第三种在不满足前两种的情况下,有其集合中还未有被统计进答案点,输出;若已有集合内的点,不输出。
\(\color{blueviolet}{CF1442D}\)
有这么一个性质,至多只有一个序列没有选满,否则一定可以通过调整得到更优解。
先考虑暴力 DP,用背包即可,现在可以枚举零碎序列,然后将其他的每个序列做 \(0/1\) 背包,枚举到的内部做一下背包即可。
这样复杂度升天,考虑用分治优化,每次处理除了当前 \([l, r]\) 以外的背包,递归下去即可,时间复杂度可以接受。
\(\color{blueviolet}{CF671C}\)
优美的题,感觉很仙。
一般这种题可以先考虑枚举左端点,然后看所有右端点的整体贡献,但这道题要求 \(\gcd\) 很不友好,无法这么处理。稍微转换一下思路,枚举答案,求每种答案的方案数,根据差分思想可以考虑求答案 \(\le i\) 的总方案数(下文称为 \(val_i\)),这样对于每个 \(i\) 求完之后可以差分得到某个值的答案,这样最终答案的计算是简单的。
设 \(i\) 为当前枚举的答案上界,我们尝试求出 \(f(l, r) \le i\) 的合法 \((l, r)\) 数量。首先观察到当 \(i\) 为极大值的时候,所有区间都是符合条件的,因此我们考虑从大到小枚举 \(i\) 每次修改贡献的变化量。
固定现在枚举到的 \(i\),设 \(nex_j\) 为对于第 \(j\) 个数,在保证 \(f(j, r) \le i\) 的条件下的最小的 \(r\),若不存在这样的 \(r\) 则 \(nex_j = n + 1\)。于是有:
所以只需要考虑维护 \(nex_j\) 的和即可,现在考虑当 \(i\) 变为 \(i - 1\) 我们修改什么。显然地,对于所有答案等于 \(i\) 的区间我们需要舍去,而只有是 \(i\) 的倍数的数才能造成贡献。在某个所选区间外(即没有删除的数中),\(i\) 的倍数至多出现一次时,此区间才可以合法,换句话说,我们需要将所有区间外存在多个 \(i\) 的倍数的区间扩展,考虑分类讨论进行扩展。
设 \(p_1, p_2, \dots, p_{k - 1}, p_k\) 表示 \(i\) 的倍数的出现位置(\(p_t < p_{t + 1} \quad (1 \le t < n)\)),分以下几种进行讨论:
-
\(1 \le j \le p_1\):此时区间左侧没有 \(i\) 的倍数,所以我们可以让区间右侧出现至多一个 \(i\) 的倍数,有 \(nex_j \leftarrow \max\{nex_j, p_{k - 1}\}\)。
-
\(p_1 < j \le p_2\):此时区间左侧有一个 \(i\) 的倍数,所以我们必须让区间包括右侧所有 \(i\) 的倍数,有 \(nex_j \leftarrow \max\{nex_j, p_k\}\)。
-
\(p_2 < j\):此时我们不论如何修改 \(nex_j\) 都没有合法的值,因为区间左侧永远有至少两个 \(i\) 的倍数,所以 \(nex_j \leftarrow n + 1\)。
我们知道维护逻辑后考虑维护方式,这个东西是一个区间对某个数取 \(\max\),全局询问和的东西。
单纯的维护是较为困难的,我们需要注意到 \(nex_j\) 在 \(i\) 固定时的取值是单调不降的,也就是说区间 \([l, r]\) 对某数 \(v\) 取 \(\max\) 等价于将某段区间 \([l, x]\) 全都赋值为 \(v\)(也可能完全不赋值),这个东西是可以用线段树上二分解决的。所以考虑将 \(nex_j\) 扔到线段树上维护,线段树上二分时需要注意边界以及返回条件。
目前为止还没有提到 \(p\) 的求法,我们发现只有 \(p_1, p_2, p_{k - 1}, p_k\) 是有用的,所以对于每个数字只需要求出其倍数的前两次出现和后两次出现即可。维护方式是简单的,首先预处理每个数的约数,复杂度是 \(n\ln n\) 的,然后对于每个输入的 \(a_i\) 都枚举其因数,用 \(i\) 去更新维护的 \(p\),详见代码。这里因为 \(a_i\) 互不相同所以复杂度是调和级数的,如果 \(a_i\) 都拉满并且相同,那预处理复杂度上界应该就是 \(n\sqrt V\) 了。
最后注意所有 \(nex_j\) 初值都有 \(nex_j = j\)。
\(\color{blueviolet}{CF1394D}\)
首先转化题意,相当于对于每个边选定其方向,然后合并合法路径减小总代价。
考虑没有 \(b_i = b_j \quad (i \not= j)\) 情况,也就是说相邻点对的大小关系是固定的。此时对于任意边 \((u, v) \quad (b_u < b_v)\),都钦定方向 \(u \to v\) 是最优的。(或者都钦定为 \(v \to u\),这两种方式等价,此题解中采用 \(u \to v\)。)此时一个点 \(u\) 贡献的代价 \(val_u\) 为 \(\max \{ d0_i, d1_i \} \times a_u\),其中 \(d0_u, d1_u\) 分别表示其入度和出度。总代价即所有点代价之和。
重新考虑原问题,我们设 \(f_{i, 0/1}\) 表示节点 \(i\) 子树内,在 \((i, fa_i)\) 这条边被钦定为向上/向下的最小代价。假设现在正在处理节点 \(u\),对于 \(b_v \not= b_u\) 的子节点 \(u\) 的贡献是固定的,我们只需要考虑 \(b_v = b_u\) 的贡献。我们先钦定这些边都是向上的,即 \(v \to u\),接下来的问题就是从这些子节点中挑一些将其钦定为 \(u \to v\),使得总代价最小。调整一个点对于 \(a_u\) 的数量贡献是固定的,于是我们贪心地优先调整 \(f_{u, 1} - f_{u, v}\) 较小的点。
考虑记录所有的 \(b_u = b_v\) 的 \(v\),将其按照 \(f_{u, 1} - f_{u, v}\) 从小到大排序,每次调整贡献并尝试更新。
特别地,考虑 \(f_{u, 0}\) 使 \(u\) 的出度加一,\(f_{u, 1}\) 使 \(u\) 的入度加一,这考虑的是边 \((u, fa_u)\) 被钦定的方向,如果 \(b_u \not= b_v\),那么 \(0/1\) 状态中只有一个会被使用。
设 \(T_u\) 表示 \(u\) 的子树,\(T0_u\) 表示被钦定为 \(v \to u\) 的点 \(v\) 的集合,\(T1_u\) 表示被钦定为 \(u \to v\) 的点 \(v\) 的集合(向上/向下连边的两个子节点集合),于是有以下形式化的转移:
以上式子中的 \(\left[u \not= 1\right]\) 表示以 \(1\) 为根进行 DP 时,其没有父节点,也就不存在与父节点连边的那个度数。
\(\color{blueviolet}{CF842E}\)
神仙题。
主要用到一个性质,多条直径一定至少交于一点或一条边。
考虑一个交点,将直径分为两段,这两段长度可能一样可能不一样(与直径长度奇偶性相关),只需考虑不一样的情况。
设两段端点集合为 \(s1, s2\),每次加入一个点 \(i\),跟两集合内任意一点求距离设为 \(d_1, d_2\)。若 \(d_1, d_2\) 其中一个能更新直径,以 \(d_1\) 为例,那么 \(s_2\) 中的点可能失效,考虑其不失效的充要条件为 \(dis(x, i) = d_1\) 其中 \(x \in s_2\),现在这样的点符合 \(s_1\) 的条件,加入 \(s_1\) 即可,然后清空 \(s_2\)。
每次模拟上述过程,输出两集合大小之和即可。
\(\color{blueviolet}{CF521D}\)
最开始看错题了以为是水题,漏掉了至多选 \(m\) 个的条件。
首先不难想到一些结论:
- 若选定了一些操作,那么操作顺序一定是赋值、加法、乘法。
- 对于一个数来说,赋值至多赋一次。
- 对于一个数来说,一定优先选择大的加法。
- 乘法的贡献与乘的位置无关,只与乘的数有关,所以一定是选最大的一些乘法。
不难想到如果只有乘法和加法,问题也是简单的,因为加法的选择一定从高到低,这样可以计算出选择每个加法的实际贡献,转成乘以一个实数。
然后想到赋值只有一次,对于数字的影响也可以看做加法,于是这题就做完了。
CF *3000-*3100
\(\color{blueviolet}{CF1583G}\)
考虑两个传送区间的关系:
- 无交集,状态互不影响。
- 相交,两者依然不会影响对方的状态。
- 包含,则大区间传送时会影响所有小区间的状态。
考虑走到一个区间 \(i\) 时(假设不存在 \(l_x < l_i \land r_x > l_i\) 的 \(x\) 这样的区间),先会将所有包含的小区间走一遍,然后传送回来,再将所有小区间再走一遍,最后走出区间。
将这个过程分为两部分(都包含传送回来这一过程):
- 走小区间再传送回来。
- 传送回来再走小区间。
这两部分的传送次数都是一样的,将其设为 \(f_i\),可以得到转移 \(f_i = 1 + \sum\limits_{l_x > l_i \land r _x < r_i} f_x\),意义上就是内部所有小区间走一遍的传送次数加上自己传送一次的总和。
这个显然可以用数据结构维护二维偏序解决。
考虑如何统计答案,如果一个区间需要被关闭,那么首先在它左侧无交集的所有区间都需要被关闭。
在左侧相交的区间也需要关闭。
然后下一过程是从区间左侧走到区间右侧再传送过程,这个过程传送贡献即 \(f_i\)。
所以对以上三种区间统计答案即可。
- 当前区间需要被关闭。
- 当前区间交在某个需要被关闭的区间左侧。
- 当前区间完全存在于某个需要被关闭的区间左侧。
二位数点即可。
\(\color{black}{CF1569F}\)
这么牛的题。
数据范围很小,不是搜索就是状压,但实际上这题两个都用到了。
初具人形,入手:
考虑一下纯暴力复杂度,应该是 \(O(n!k^nn)\),蠢得很的复杂度。
我们发现回文串最多用到 \(\frac{n}{2}\) 种字符,所以 \(k\) 种字符可能不全用上。
这启发我们钦定一共用 \(t\) 种字符,再枚举每个点用什么字符,最后对于合法方案数量乘上一个 \(A_k^t\)(从 \(k\) 个字符中选出 \(t\) 个进行排列),换句话说,我们并不关心每个点具体是什么字符。
对于一种用 \(t\) 种字符覆盖 \(n\) 个点的方案(\(t\) 种字符都要出现过),会产生 \(A_k ^t\) 的贡献(\(t > k\) 时为 \(0\))。
合法的覆盖方案指存在一条回文曼哈顿路径。
混沌初开,第一部分枚举:
观察一条曼哈顿路径 \(p_1 \to p_2 \to \dots \to p_n\),如果其所代表的串是一个回文串,那么有 \(ch_{p_1} = ch_{p_n}, ch_{p_2} = ch_{p_{n - 1}} \dots\),其中 \(ch_i\) 表示第 \(i\) 个点上的字符。
所以我们考虑将点分成一对一对的,如 \(\{x_1, y_1\}, \{x_2, y_2\}, \dots, \{x_{\frac{n}{2}}, y_{\frac{n}{2}}\}\),为了保证不重不漏,我们做以下要求:
- 区间 \([1, n]\) 中的每个整数出现且只出现一次。
- 对于 \(i \in [1, \frac{n}{2}]\), 都有 \(x_i < y_i\)。(强制每个数对无序。)
- 对于 \(i \in [1, \frac{n}{2})\),都有 \(x_i < x_{i +1}, y_i < y_{i + 1}\)。(使得数对之间的顺序固定。)
这样的限制也方便我们枚举所有情况,可以考虑如下过程:
- 从所有未被选择过的数中挑选一个最小的作为当前数对的 \(x\)。
- 枚举所有大于 \(x\) 并且未被选择的 \(y\)。
- 重复如上操作直到所有数字都被选择过一次。
这样操作方案数也是好算的,第一次选择有 \(n - 1\) 中,去掉第一次的 \(x, y\) 之后又有 \(n - 3\) 种选择,以此类推,总方案数为 \((n - 1)(n - 3) \dots 2 \times 1 \le 10395\)。
渐入佳境,判断是否存在的合法路径符合上述枚举:
对于已经枚举出的数对序列 \(\{x_1, y_1\}, \{x_2, y_2\}, \dots, \{x_{\frac{n}{2}}, y_{\frac{n}{2}}\}\),我们考虑用状压 DP 去判断是否存在一条曼哈顿路径使得每个 \(x_i, y_i\) 一一对应。
我们考虑从中间向两边依次放置数对,使得其组成一个合法曼哈顿路径。数对数量最多为 \(6\),可以用状压表示其是否放置过。
设 \(f_{i, u, v}\) 表示是否存在满足以下条件的路径:集合 \(i\) 内的数对都放置过了,现在两侧放置的点分别为 \(u, v\)。我们尝试用刷表法解决。
枚举接下来要放置的数对(编号为 \(j\)),设其为 \(tu, tv\),当 \(f_{i, u, v} = 1\),并且存在边 \((u, tu), (v, tv)\)(或者 \((u, tv), (v, tu)\))时,\(f_{i \cup \{j\}, tu, tv} \leftarrow 1\)。
最后只要判断全集时是否存在一个数对放在最外侧使得其 \(f\) 数组值为 \(1\) 即可。
其实上述状态可以优化为两维 \(f_{i, id}\) 表示是否存在满足以下条件的路径:集合 \(i\) 内的数对都放置过了,现在两侧放置的点为 \(x_{id}, y_{id}\)。
但是三维可过,所以就没写优化的版本。三维 DP 的复杂度大概为 \(O(2^{\frac{n}{2}}\times\frac{n^3}{2})\)。
胜利在望,第二部分枚举,给每个点对分配字符:
我们现在已经得到了一个合法点对序列,考虑对每个点对分配颜色,成为一种方案。
按顺序处理每一个点对,我们可以分配一个新种类的字符给它,并将字符种类加一;也可以分配一个曾经出现过的字符给它。
这样每一个点都得到了一种字符,但我们考虑这样处理方案实际上会有重复,给出如下例子:
现有两组合法点对序列 \(\{1, 2\}, \{3, 4\}\) 以及 \(\{1, 3\},\{2, 4\}\),当一共只有 \(1\) 种字符的时候,两个序列都会给出 \(ch = {1, 1, 1, 1}\) 的字符分配方案。
这样一种方案算了多次,我们考虑去重。将字符的分配数组 \(ch\) 转成 vector 放到 set 里,最后统计答案的时候遍历即可。
算一下总方案数,先考虑一个合法点对序列最多得到多少种不同的字符分配方案。这个问题相当于现有 \(\frac{n}{2}\) 个不同的元素,要将其分配至至多 \(\frac{n}{2}\) 个集合中的方案。联想到 \(\frac{n}{2}\) 个不同球放进 \(i\) 个相同盒子的数量,即第二类斯特林数,但 \(i \in [1, \frac{n}{2}]\),将枚举出来的加和即方案数,上限应该为 \(203\)。
所以总共去重前方案数上限为 \(10395 \times 203\)。
开香槟咯!统计答案:
从刚才去重过的 set 中遍历每个字符分配集合,其中每个数字对应的字符编号最大值 \(mxv\) 即这个方案的字符总种类数,答案累加上 \(A_k ^{mxv}\) 即可。
\(\color{black}{CF1552G}\)
神仙题。
首先考虑一个转化,如果给出的操作可以对任意一种初始序列排序,当且仅当它可以对任意一种初始的 \(0/1\) 序列排序,证明是简单的。
对于一种初始序列,对于其任意一个数字 \(x\),将小于 \(x\) 的变为 \(0\),大于等于 \(x\) 的变为 \(1\)。如果给出的操作能对如上构造出来的所有 \(0/1\) 序列排序,那么它一定可以对初始序列排序,故上述转化成立。
对于每种初始 \(0/1\) 序列,只要最终能转化为 \(00 \dots 011 \dots 1\) 的形式就合法。
\(n\) 的范围足够小,我们可以状压到 long long 中,但并不能暴力枚举,\(O(2^{n})\) 的复杂度我们是无法接受的。
对于一次排序,我们只关心 \(0/1\) 的个数,而不关心每个位置具体是什么。
举例来说,对于一次涉及到三个位置的排序,当这三个位置分别为 \(011\) 或 \(101\) 或 \(110\) 的时候是等价的,排完序之后都为 \(011\)。
我们考虑依次处理每个操作,对于没固定的位置枚举可能出现的状态,可以理解为对于每个位置在第一次对它进行操作后确定其值。
依然举例来说,初始序列是不确定的,如 \(????\) 的形式。
假设第一次操作处理了位置 \(2, 3, 4\),那么我们将确定这三位的值,于是序列变为 \(?111\) 或 \(?011\) 或 \(?001\) 或 \(?000\)。
也就是说对于当前操作的所有位置中,假设已确定的 \(0\) 有 \(cnt_0\) 个,\(1\) 有 \(cnt_1\) 个,那么这些位置排序后前 \(cnt_0\) 个位置都必须为 \(0\),后 \(cnt_1\) 个位置都必须为 \(1\),中间未确定的地方就可以枚举 \(0, 1\) 分界点来枚举状态了。
当所有操作都处理完之后只需要判断当前状态是否合法即可。
说一些实现细节,设 \(S_i\) 表示第 \(i\) 次操作涉及到的位置集合,\(T_i\) 表示前 \(i\) 次操作涉及到的位置集合。
首先对于最终状态 \(st\) 我们可以 \(O(1)\) 判断是否合法,先将其取反,那么其若合法则变为形如 \(11 \dots 100 \dots 0\) 的状态,加一后可以得到 \(00 \dots 0100 \dots 0\) 的形式,此时只要判断是否只有一个 \(1\) 即可,即 lobit(st) == st
。
对于取 \(cnt_0, cnt_1\) 可以预处理 \(S, T\) 来用位运算 \(O(1)\) 处理。
下面分析一下复杂度,采用了官方题解的证明。
设 \(d_i = |S_i \setminus T_{i - 1}|\),其中 \(A \setminus B\) 即集合减法,可以理解为从 \(A\) 中去掉与 \(B\) 相交的部分。
有复杂度为 \(O(n\prod\limits_{i = 1}^{k} (d_i + 1))\)。
由于 \(\sum \limits_{i = 1}^k (d_i + 1) \le n + k\),由基本不等式可以知道 \(\prod\limits_{i = 1}^{k} (d_i + 1) \le \left(\frac{n + k}{k}\right)^k\)。
故复杂度为 \(O(\left(\frac{n + k}{k}\right)^k)\)。
\(\color{blueviolet}{CF739E}\)
暴力是简单的,不难想出 \(f_{i, j, k}\) 表示前 \(i\) 个宝可梦用了 \(j\) 个宝贝球,\(k\) 个超级球所能得到的最大期望,复杂度是 \(O(n^3)\) 的,可以考虑优化掉后一维或两维,换成 wqs 二分即可。
\(\color{blueviolet}{CF1842H}\)
非常好题目啊。
考虑令 \(x_i \leftarrow x_i +0.5\),限制变为与 \(0\) 的大小关系,注意到这个式子是否成立只需要考虑绝对值较大的数的正负,考虑从小到大加入 \(x_i\),枚举状态,再枚举加入哪一个求出合法方案,除以总方案即答案。