Codeforces & AtCoder 部分好题总结

Codeforces & AtCoder 部分好题总结

Codeforces

CF232E

题意

在一个 \(n \times m\) 的网格上,有一些格子是障碍。给定 \(q\) 个询问,每次询问是否能通过向下走向右走从格子 \((x_1,y_1)\) 走到格子 \((x_2,y_2)\)

数据范围:\(1 \leq n \leq 500\)\(1 \leq q \leq 6 \times 10^5\)

做法

考虑将询问离线,设当前处理到 \([l, r]\) 行,令 \(mid = \frac{(l + r)}{2}\),处理所有跨越 \(mid\) 的询问,然后递归处理左右区间即可。

如何处理跨越 \(mid\) 的询问呢?考虑到这些询问都经过了 \(mid\) 这一行中的某些点,我们记 \(go(i, j, k)\) 表示是否能从 \((i, j)\) 走到 \((mid, k)\)(若 \(i > mid\) 则表示为 是否能从 \((mid, k)\) 走到 \((i, j)\)),显然求 \(go\) 可以通过 bitset 优化。

最后时间复杂度为 \(\mathcal O(\frac{nm^2}{\omega} \log n + q (\log n +\frac{n}{\omega}))\)

如果强制在线,可以使用猫树,实际上就是将上述分治的信息记录下来。

评测链接

CF786B

题意

\(n\) 个点,\(q\) 次操作。有三种操作。

  1. 给定 \(v, u, w\),表示由 \(v\)\(u\) 连一条权值为 \(w\) 的边;
  2. 给定 \(v, l, r, w\),表示由 \(v\)\([l, r]\) 中的每个点都连一条权值为 \(w\) 的边;
  3. 给定 \(v, l, r, w\),表示由 \([l, r]\) 中的每个点都向 \(v\) 连一条权值为 \(w\) 的边;

要求 \(s\) 到各个点的最短距离。

数据范围:\(1 \leq n, q \leq 10^5\)\(1 \leq w \leq 10^9\)

做法

经典题。

暴力连边固然会 TLE,发现是对一个区间进行操作,考虑使用线段树来维护。

建两颗线段树,一棵由 \(p\)\(p\) 的两个儿子连权值为 \(0\) 的边,另一棵由 \(p\) 的两个儿子向 \(p\) 连权值为 \(0\) 的边。这样对于操作 2. 3. \(v\) 就只需要对 \(\log n\) 个结点连边即可。由于两棵树的叶子结点代表的都是相同的点,所以两两也需要连权值为 \(0\) 的边。然后跑 Dijkstra 即可。

时间复杂度:\(\mathcal O((n + q \log n) \log n)\)

评测链接

CF811E

题意

在一个 \(n \times m\) 的网格上每个格子都有颜色,\(q\) 次询问,每次询问只保留 \(l\)\(r\) 列时有多少个四连通的颜色块。两个格子同色但不连通算在不同的颜色块内。

数据范围:\(1 \leq n \leq 10\)\(1 \leq m, q \leq 10^5\)

做法

线段树 + 并查集。区间 \([l, r]\) 表示 \((1, l)\) 为左上角,\((n, r)\) 为右下角的矩阵。

对于一个区间 \([l, r]\) 维护两个值:

  1. 该区间四连通的颜色块个数。
  2. \(l\)\(n\) 个元素所属集合以及 \(r\)\(n\) 个元素所属集合。

有了上述两个值,我们发现合并两个区间只需要使用并查集维护即可。

时间复杂度:\(\mathcal O(n m \alpha(nm) + nq \log m)\)

评测链接

CF1132G

题意

定义一个序列的最长贪心严格上升子序列为:对于选出的子序列其中相邻两项 \(i,j\),不存在 \(k(i < k < j)\),满足在原序列 \(a\) 中,有 \(a_i < a_k\),也就是选择一个元素后必须选择它之后第一个大于它的元素。

给定一个长度为 \(n\) 的序列,同时给定一个常数 \(k\),求该序列的所有长度为 \(k\) 的子区间的最长贪心严格上升子序列的长度。

数据范围:\(1 \leq k \leq n \leq 10^6\)\(1 \leq a_i \leq n\)

做法

考虑将下标 \(x\) 之后第一个大于它的元素下标 \(y\) 记为 \(x\) 的父亲(若不存在则将 \(0\) 记为 \(x\) 的父亲),那么最后会形成一棵树,问题转化为找出不包含零结点的最大深度。考虑加入 \(a_x\) 对答案的影响,就是 \(x\) 的所有儿子的深度 \(+1\),删去也就对应着深度 \(-1\),那么就很好处理了,我们建出这颗树,之后使用线段树维护深度即可。查询就只需要查询最大深度即可。

时间复杂度:\(\mathcal O(n \log n)\)

评测链接

CF1659E

题意

给定一张 \(n\) 个点 \(m\) 条边(边有边权)的无向联通图,定义一条路径的长度为 \(\operatorname{mex}\{w_1, w_1 \& w_2, \cdots, w_1 \& w_2 \&\cdots \&w_k\}\),其中 \(k\) 为这条路径的长度,\(w_1, w_2, \cdots, w_k\) 表示这条路径上依次经过的边的边权。现在有 \(q\) 次询问,每次询问给出 \(u, v\),要你求出 \(u \to v\) 的最小路径长度。

数据范围:\(2 \le n \leq 10^5\)\(n - 1 \leq m \leq \min\left(\dfrac{n (n - 1)}{2}, 10^5\right)\)\(0 \leq w \leq 2 ^ {30}\)\(1 \leq q \leq 10^5\)

做法

定理 1. \(1\)\(2\) 不会同时出现在一条路径的 \(\operatorname{mex}\) 中。

证明如下:使用反证法证明,假设 \(1\) 先出现在该路径的 \(\operatorname{mex}\) 中,考虑到 \(1\) 的二进制下的第二位是 \(0\),且进行的是 \(\&\) 运算,于是后面的值中第二位不可能 \(1\),也就证明了 \(2\) 不可能出现在该路径的 \(\operatorname{mex}\) 中;对于 \(2\) 先出现在该路径的 \(\operatorname{mex}\) 中的情况同理。

由定理 1. 可知:任何一个路径其长度不可能大于 \(2\)

那么只需要判断是否存在长度为 \(0 / 1\) 的路径,若不存在则答案为 \(2\)

  1. 判断是否存在长度为 \(0\) 的路径,即存在某一位 \(k\),使得路径上每一条边的边权在第 \(k\) 位上均为 \(1\)。考虑枚举 \(k \in [0, 29]\),将边权在第 \(k\) 位为 \(1\) 的边保留下来,这样会形成 \(30\) 个新图,对每个新图都使用并查集维护连通性即可。对于询问 \((u, v)\),我们只需判断是否有新图满足 \(u, v\) 在同一个的连通块,若有则代表存在长度为 \(0\) 的路径。
  2. 判断是否存在长度为 \(1\) 的路径,考虑这条路径如何实现,一定是先经过若干位奇数边权(当前长度 \(>1\)),然后经过一个偶数边权,最后随便经过某些路径,最后到达终点。考虑还是先枚举 \(k \in [1, 29]\),使得每一条边都只经过边权在第 \(0 / k\) 位为 \(1\) 的边,照样用并查集维护这些新图,然后对于边权为偶数的边 \((u, v)\),我们在所有新图上 \(u, v\) 所在的连通块打上标记。对于询问 \((u, v)\),我们只需判断是否有新图满足 \(u\) 的连通块上有标记,若有标记则代表存在长度为 \(1\) 的路径。

时间复杂度 \(\mathcal O(n \log w + (m + q) \cdot \alpha(n)\log w)\)

评测链接

CF1661E

题意

在一个 \(3 \times n\) 的网格上每个格子都有 0 / 1,\(q\) 次询问,每次询问只保留 \(l\)\(r\) 列时有多少个只包含 1 的连通块。

数据范围:\(1 \leq n \leq 5 \times 10^5\)\(1 \leq q \leq 3 \times 10^5\)

做法

和 CF811E 一致,不再赘述。

评测链接

CF1661F

题意

直线上有 \(n + 1\) 个传送器,分别位于 \(0, a_1, a_2, \cdots, a_n\),如果两个点都有传送器,则可以从点 \(x\) 传送到 \(y\),并且花费 \((y - x)^2\),你想要安装一些额外的传送器(只能在整点上安装),使得可以从 \(0\) 传送到 \(a_n\) 且花费少于 \(m\)。你要最小化这个安装数量。

数据范围:\(1 \leq n \leq 2 \times 10^5\)\(1 \leq a \leq 10^9\)\(a_n \leq m \leq 10^{18}\)

做法

首先可以发现每一段中安装传送器与其他段是互不干扰的。我们设 \(f(x, k)\) 表示将长度为 \(x\) 的段分为 \(k\) 段(即安装 \(k - 1\) 个传送器)所需的最小费用。\(f(x, k)\) 的计算是很容易的,显然,这 \(k\) 段的长度两两顶多差 \(1\)(如果有两段长度相差大于 \(1\),调整这两段的大小一定能更小化费用),具体的,我们设长度为 \(w\) 的段有 \(b\) 个,长度为 \(w + 1\) 的段有 \(c\) 个,可以列出方程组:

\[\begin{cases} wb + (w + 1)c = x \\ b + c = k \end{cases} \]

可以得到:\(wk + c = x\),我们要最小化 \(c\),故可以得到:\(c = x \bmod k\)\(b = k - c\)\(w = \frac{(x - c)}{k}\)

\(f(x, k) = w^2\times b + (w + 1)^2 \times c\)

引理 1. \(\forall k\in[1, x]\),都有 \(f(x, k - 1) - f(x, k) \geq f(x, k) - f(k + 1)\)

看起来就感觉很正确,感性理解一下,具体证明可以见 Link

现在有了引理 1,我们考虑怎么做。

我们可以转换一下思路,原先花费为 \(c = \sum_{i = 1}^n (a_i - a_{i - 1})^2\)\(a_0 = 0\)),差异为 \(c - m\),现在有 \(n\) 个升级列表,假设第 \(i\) 段升级了 \(j\) 次,每次升级都可以理解为将差异减小了 \(f(a_i - a_{i - 1}, j - 1) - f(a_i - a_{i - 1}, j)\),比如将第 \(i\) 段升级了 \(2\) 次,则总减小量为 \(f(a_i - a_{i - 1}, 0) - f(a_i - a_{i - 1}, 1) + f(a_i - a_{i - 1}, 1) - f(a_i - a_{i - 1}, 2) = f(a_i - a_{i - 1}, 0) - f(a_i - a_{i - 1}, 2)\),我们发现这正好符合差异减小的定义。因此,问题转化为最少升级几次可以使得总减小量不小于 \(c - m\)

容易发现,我们每次都选择最大差异量的进行升级最优秀,根据引理 1,这么选择一定满足选取某一段连续升级 \(k\) 次最优,这也正好符合上文总减小量的含义。

显然**最后一次升级的差异量 **\(\Delta\) 是有单调性的,我们考虑二分这个差异量 \(\Delta\),判断升级所有差异量大于等于 \(\Delta\) 时是否能满足总花费小于等于 \(m\)(对应着总减小量是否小于 \(c - m\)),判断时对于每一段再次进行二分,找到最大的 \(k\) 使得 \(f(a_i - a_{i - 1}, k - 1) - f(a_i - a_{i - 1}, k) \geq \Delta\),对应的也就能判断出当前差异量下是否能满足花费小于等于 \(m\)

我们找到了这个满足条件且最大的 \(\Delta\),设 \(g(\Delta)\) 为该情况下的总花费,\(h(\Delta)\) 为该情况下的安装数量。那么答案就是 \(h(\Delta)\) 吗?并不,我们注意到只有某些段的差异量要取到 \(\Delta\),有 \(\left \lfloor \frac{m - g(\Delta)}{\Delta} \right \rfloor\) 段是无需更新到 \(\Delta\) 的,故答案便为 \(h(\Delta) - \left \lfloor \frac{m - g(\Delta)}{\Delta} \right \rfloor\)

时间复杂度 \(\mathcal O(n \log^2 A)\) \(A\) 大约为值域级别。

评测链接

CF1665E

题意

给出 \(n\) 个数 \(a_1 \sim a_n\),有 \(q\) 次询问,每次给出 \(l, r\),求 \(\min\limits_{l \leq i < j \leq r} a_i | a_j\)

数据范围:\(2 \leq n \leq 10^5\)\(0 \leq a_i < 2^{30}\)\(1 \leq q \leq 10^5\)

做法 1

考虑莫队 + Trie 树。

首先将询问离线,考虑建 01 Trie,在 Trie 树上记录结点被到达的次数 \(siz\)。考虑怎么求出答案,从根结点往下走,若走 \(0\) 边到达的结点的 \(siz\geq 2\),那么走 \(1\) 边一定不优,走 \(0\) 边往下递归即可;否则只能往走 \(1\) 边的结点递归,若此时有走 \(0\) 边的结点,我们就记录下走 \(0\) 边所能得到的值(顶多只有 \(1\) 个),然后走 \(1\) 边往下递归即可。递归到末端时记录该节点的值(若 \(\geq2\) 个则只需要记录两个,因为只有两个有用),容易发现,答案一定在记录下的值中的某两个,暴力求即可。时间复杂度 \(\mathcal O(n \sqrt{n} \log a + q \log^2 a)\)

容易发现不需要莫队,可持久化 trie 即可。时间复杂度 \(\mathcal O(n \log a + q\log^2 a)\)

评测链接

做法 2

有一个结论:如果所有数都小于 \(2^k\),那么只需要考虑 \(k + 1\) 个最小数字即可。

考虑归纳证明。

\(k=1\) 时,只有两个数字 \(0, 1\),显然只需要考虑这两个数字即可。

若结论对 \(k\) 成立,那么我们现在只需要证明结论对 \(k + 1\) 也成立即可。

  1. 所有数字中第 \(k\) 位都是 \(1\),那么无论如何答案的第 \(k\) 位一定是 \(1\),问题转化为选出两个数使得前 \(k - 1\) 位最小,由于结论对 \(k\) 成立,故此时只需要 \(k + 1\) 个数字即可;
  2. 所有数字中第 \(k\) 位是 \(0\) 的数不少于 \(2\) 个,则答案的第 \(k\) 位一定是 \(0\),此时我们只需要考虑第 \(k\) 位为 \(0\) 的数字,由于结论对 \(k\) 成立,故此时只需要 \(k + 1\) 个数字即可;
  3. 所有数字中第 \(k\) 位是 \(0\) 的数恰好只有一个,那么无论如何答案的第 \(k\) 位一定是 \(1\),我们需要找到 \(k\) 位上对应的那 \(k + 1\) 个最小的数,这些数在 \(k + 1\) 位上是前 \(k + 2\) 个最小数,故此时只需要 \(k + 2\) 个数字即可。

证毕。

线段树维护前 \(30\) 小值即可。时间复杂度 \(\mathcal O(n \log n + q \log^2 a)\)

CF1672E

题意

交互题。告诉你共有 \(n\) 个单词,现在要在 notepad.exe 中显示这 \(n\) 个单词(长度为 \(l_i\)),当 \(k\) 个单词出现在同一行时,保证这 \(k\) 个单词两两之间至少有一个空格,即长度至少为 \(S + k - 1\)\(S\) 是这 \(k\) 个单词的总长度。现在,你可以询问 \(n + 30\) 次,每次询问给出 \(w\),表示一行最长能有多少个字符,他会返回 \(h\)(若 \(w\) 小于任何一个单词的长度,那么会返回 \(0\)),表示该情况下最短的行数,你要求出 \(w \times h\) 的最小值。

数据范围:\(1 \leq n \leq 2000\)\(1 \leq l_i \leq 2000\)

做法

看到 \(n + 30\) 次询问,大概可以猜到是 \(n + \log X\) 的询问次数,首先,我们可以二分出这些单词放到同一行的长度 \(S\),此时便有一个解 \(S\),考虑将 \(h\) 增加,最优情况下这 \(h\) 行都没有多余的空格,那么面积最小为 \(S - h + 1\),又考虑到我们需要的答案一定 \(\leq S\),那么对我们有意义的面积就在 \([S - h + 1, S]\),容易发现这个区间内 \(h\) 的倍数只有一个,于是对于每个 \(h\) 都进行一次询问即可求出答案。

时间复杂度 \(\mathcal O(\log \sum_{i = 1}^n|l_i| + n)\)

评测链接

CF1672F1

题意

给出长度为 \(n\) 的数组 \(a\),你需要构造一个 \(a\) 的置换 \(b\),使得 \(b\) 经过只交换操作后成为 \(a\)最少交换次数最大

数据范围:\(2 \leq n \leq 2 \times 10^5\)\(1 \leq a_i \leq n\)

做法

\(a\) 数组中,元素 \(i\) 出现了 \(cnt_i\) 次,我们令 \(cnt_1 \geq cnt_2 \geq \cdots \geq cnt_k\)(即将元素重编号,按照出现次数排名)。

假设 \(b\) 数组已经确定,我们考虑如何求出这个最少交换次数。考虑两个图:

\(G_1\):若 \(b_i = a_j\) 则连一条 \(i \to j\) 的边,表示 \(b_i\) 最终有可能移动到位置 \(j\)

\(G_2\):对于某一种方案,若 \(b_i\) 最终要移动到位置 \(j\) 则连一条 \(i \to j\) 的边,容易发现每个点只会有一条出边和一条入边,那么最终的图一定由若干个环组成。

结论 1. 对于某一张图 \(G_2\),该方案的最少交换次数 \(F(G_2)\)\(\operatorname{size}(G_2) - \operatorname{ring}(G_2)\)(其中 \(\operatorname{size}(G)\) 是图 \(G\) 的大小,\(\operatorname {ring}(G)\) 表示图 \(G\) 环的个数)。

引理 1. 对于 \(\operatorname {size}(G) \geq 2\) 的环 \(G\),对任意两个不同结点进行交换后会成为两个环。

证明如下:

对于环 \(g_1 \to g_2 \to \cdots \to g_k\to g_1\),考虑交换 \(g_i, g_j(1 \leq i < j \leq k)\),图会变为 \(g_1 \to \cdots \to g_i \to g_{j+ 1} \to \cdots \to g_k \to g_1\)\(g_{i + 1} \to \cdots \to g_j \to g_{i + 1}\) 这两个环。

引理 2. 对于两个环,在两个环中各取一个结点进行交换后会合并为一个环。

证明如下:

对于环 \(g_1 \to g_2 \to \cdots \to g_k \to g_1\)\(f_1 \to f_2 \to \cdots \to f_h \to f_1\),考虑交换 \(g_i, f_j(1 \leq i \leq k, 1 \leq j \leq h)\),图会变为 \(g_1 \to \cdots \to g_i \to f_{j + 1} \to \cdots \to f_h \to f_1 \to \cdots \to f_j \to g_{i + 1} \to \cdots \to g_k \to g_1\) 这一个环。

引理 3. 对于一个环 \(G\),它的最少交换次数 \(F(G)\)\(\operatorname{size}(G) - 1\)

证明如下:

考虑使用数学归纳法证明:

  1. \(\operatorname{size}(G) = 1\) 时,\(F(G) = 0\)\(\operatorname{size}(G) = 2\) 时,\(F(G) = 1\)
  2. 假设当 \(\operatorname{size}(G) \leq k, k \geq 2\) 时,引理 3 成立,当 \(\operatorname{size}(G) = k + 1\) 时,肯定是交换两个不同结点,根据引理 1 可知,会分裂出两个环,每个环的大小一定 \(\leq k\),即分裂出的两个环都满足引理 3,那么就有 \(F(G) = F(G_1) + F(G_2) + 1 = \operatorname{size}(G_1) - 1 + \operatorname{size}(G_2) - 1 + 1 = \operatorname{size}(G) - 1\)。即 当 \(\operatorname{size}(G) = k + 1\) 时,\(F(G) = \operatorname{size}(G) - 1\) 也成立。故引理 3 得证。

结论 1 证明如下:

若每次操作仅对一个环内的结点进行操作,那么根据引理 3 可知,至少要进行 \(\operatorname{size}(G) - \operatorname{ring}(G)\) 次,若对不同环的结点进行操作,根据引理 2 可知环会合并,容易发现这样操作一定更劣。

结论 2. 最终方案的图中不会出现一个环内出现两个值相同的元素的情况。

证明如下:

考虑出现两个相同值元素的环:\(g_1 \to g_2 \to \cdots \to g_s \to \cdots \to g_t \to \cdots \to g_k \to g_1\)(其中 \(\operatorname{val}(g_s) = \operatorname{val}(g_t)\)),那么根据结论 1,我们会最大化环的个数从而使得交换次数最少,那么上述的环可以分为两个环:\(g_1 \to \cdots \to g_s \to g_{t + 1} \to \cdots \to g_k \to g_1\)\(g_{s + 1} \to \cdots \to g_t \to g_{s + 1}\),故不可能出现一个环内出现两个值相同的元素的情况。

回到本题,根据结论 1 容易发现我们需要最小化最大化环的个数。设 \(cnt\)\(a\) 中出现次数最多的数的个数。那么根据结论 2,这个环的个数至少有 \(cnt\) 个,即最少交换次数最多为 \(n - cnt\),下面给出一种构造方案使得答案为 \(n - cnt\)

构造如下:

  1. 尽可能多地选定各不相同的几个数;
  2. 将它们按照 大小顺序 循环移动,每个数移动到恰好大于它的那个位置(最大的数移动到 \(1\) )。

如:

\[a = (1, 3, 2, 4, 2, 1, 4) \\ b = (*, *, *, *, *, *, *) \\ a = (\pmb1, \pmb3, \pmb2, \pmb4, 2, 1, 4) \\ b = (4, 2, 1, 3, *, *, *) \\ a = (1, 3, 2, 4, \pmb2, \pmb1, \pmb4) \\ b = (4, 2, 1, 3, 1, 4, 2) \\ \]

结论 3. 按照上述构造的 \(b\),对应的图 \(G_1\) 中不存在环不经过出现次数最多的元素 \(1\)

证明如下:

若存在这么一个环,我们考虑这个环 \(g_1 \to g_2 \to \cdots \to g_k \to g_1\),因为不经过 \(1\),所以满足如下式子:

\[b_{g_1} = a_{g_2} > b_{g_2} = a_{g_3} > \cdots > b_{g_k} = a_{g_1} > b_{g_1} \]

显然矛盾,故结论 3 得证。

考虑如何方便的构造出上述的 \(b\),我们将 \(a\) 进行排序,然后按照 \(cnt\) 进行循环分组(\(a_1\) 放到 \(a_{1 + cnt}\) 下,\(a_2\) 放到 \(a_{2 + cnt}\) 下 ... \(a_{n - cnt + 1} \sim a_n\) 均放到 \(a_1\) 下),这样便能构造出 \(cnt\) 个环,且满足上述条件。

时间复杂度:\(\mathcal O(n \log n)\)

评测链接

CF1672F2

题意

前情提要为 CF1672F1。

给出两个长度为 \(n\) 的数组 \(a\)\(b\),你需要判断 \(b\) 是否是满足最少交换次数最大的一个置换。

数据范围:\(2 \leq n \leq 2 \times 10^5\)\(1 \leq a_i \leq n\)\(1 \leq b_i \leq n\)

做法

根据 CF1672F1 所述,若每个环中都有出现次数最多的元素,那么这个构造就是合法的,考虑将这个出现次数最多的元素删去,若剩下的图中还存在环,那么 \(b\) 就是不合法的,否则 \(b\) 就是合法的(原因是每个点都一定属于某个环)。

但是直接连边的边数是 \(n^2\) 级别的,考虑建虚拟结点,对应的虚拟节点连向对应 \(a_i\) 相同的结点,那么 \(b_i\) 就只需要对对应的虚拟节点连边即可,这样不影响联通性,并且将边数降到了 \(n\) 级别。跑拓扑判断有无环即可。

时间复杂度 \(\mathcal O(n)\)

评测链接

CF1672H

题意

给你一个长度为 \(n\) 的字符串 \(a\),仅由数字 \(0\)\(1\) 组成。给你 \(q\) 个询问。 每次询问给出 \(l, r(1 \leq l \leq r \leq n)\),令 \(s=a[l,r]\)

你可以对 \(s\) 进行如下操作:

  1. 选择 \(x, y(1 \leq x \leq y \leq |s|)\) 。令 \(t=s[x,y]\)。那么 \(\forall i \in[1, |t| - 1] \bigcup \mathbb{Z}\),都有 \(t_i \not =t_{i+1}\),若 \(|t| = 1\),则 \(t\) 也是一个满足条件的子串;
  2. \(s\) 中删除子串 \(s[x,y]\)

对于每个查询,找到使 \(s\) 为空字符串所需的最小操作数。

数据范围:\(1 \leq n, q \leq 2 \times 10^5\)

做法

首先,我们记 \(x\)\(00\) 连续的数量,\(y\)\(11\) 连续的数量。

有一个明显的结论:每次操作一定是对最长的可行区间进行操作。

操作一个长度为偶数的区间后,\(x, y\) 均会减少 \(1\),我们称其为操作 1;操作一个长度为奇数的区间后,\(x, y\) 中有一个会减少 \(1\),我们称其为操作 2。

显然,我们会尽可能使用操作 1,然后使用操作 2 将 \(x, y\) 都变为 \(0\),这部分操作数为 \(\max(x, y)\),最后只需要一步便可清空。故答案为 \(\max(x, y) + 1\)

记个前缀和即可 \(\mathcal O(1)\) 回答询问。时间复杂度 \(\mathcal O(n + q)\)

评测链接

AtCoder

ARC066D

题意

\(n\) 道题目,做第 \(i\) 道题花费的时间为 \(t_i\),定义得分为:满足条件的二元组 \((l,r)\) 的个数减去解决做了的题所花费的时间。其中,二元组 \((l, r)\) 需要满足的条件是:对于所有满足 \(l \le i \le r\)\(i\),第 \(i\) 题都做了。另外,\(l\)\(r\) 还需满足 \(1 \le l \le r \le N\)

\(m\) 次修改,每次修改会将 \(t_p\) 修改为 \(x\),你需要输出每次修改后的最大得分。修改独立

数据范围:\(1 \leq n \leq 3 \times 10^5\)\(1 \leq m \leq 3 \times 10^5\)

做法

首先考虑不修改的情况。记 \(\operatorname{sum}(i)\) 表示前 \(i\) 题所花费的总时间,\(f(i)\) 表示前 \(i\) 题所能得到的最大得分。则有:

\[f(i) = \max \left\{ f(i - 1), \max_{j = 0}^{i - 1} \left\{f(j) + \frac{(i - j) \times (i - j + 1)}{2} - \operatorname{sum}(i) + \operatorname{sum}(j)\right\} \right\} \]

考虑后面那个式子:

\[f(j) + \operatorname{sum}(j) + \frac{j^2 - j}{2} = ij + f(i) + \operatorname{sum}(i) - \frac{i^2 + i}{2} \]

记:

\[y = f(j) + \operatorname{sum}(j) + \frac{j^2 - j}{2} \\ k = i \\ x = j \\ b = f(i) + \operatorname{sum}(i) - \frac{i^2 + i}{2} \\ \]

斜率优化,\(i\)\(j\) 都递增,使用单调栈维护即可。

考虑再设 \(g(i)\) 表示后 \(i\) 题所能得到的最大得分,维护方法如上。

考虑修改了 \(t_p\)\(x\),此时分两种情况讨论。

  1. 若没选择 \(p\),则最大答案为 \(f(p - 1) + g(p + 1)\)
  2. 若选择了 \(p\),则最大答案为 \(h(p) - t_p + x\),其中 \(h(p)\) 表示强制选择了 \(p\) 所能得到的最大分数。

答案取两种情况的最大值即可。现在问题转化为如何求 \(h\)。考虑分治。

设当前分治区间为 \([l, r]\),记 \(mid = (l + r) / 2\)\(q(i)\) 表示左端点为 \([l, mid]\) 右端点为 \(i\),其最大价值。

\[q(i) = \max_{j = l - 1}^{mid - 1} \left\{f(j) + g(i + 1) + \frac{(i - j) \times (i - j + 1)}{2} - \operatorname{sum}(i) + \operatorname{sum}(j) \right \} \]

\[f(j) + \operatorname{sum}(j) + \frac{j^2 - j}{2} = ij + q(i) - g(i + 1) + \operatorname{sum}(i) - \frac{i^2 + i}{2} \]

\(p(i)\) 表示左端点为 \(i\),右端点为 \([mid + 1, r]\),其最大价值。

\[p(i + 1) = \max_{j = mid + 1}^{r} \left\{f(i) + g(j + 1) + \frac{(j - i) \times (j - i + 1)}{2} - \operatorname{sum}(j) + \operatorname{sum}(i) \right \} \]

两个式子都可以斜率优化,并且容易发现 \(q(i)\) 可以更新 \(h(j)(j \in [mid + 1, i])\)\(p(i)\) 可以更新 \(h(j)(j \in [i, mid])\),对应更新即可。

时间复杂度 \(\mathcal O(n \log n + m)\)

评测链接

ABC247F

题意

\(n\) 张牌,正面和背面都是 \(1 \sim n\) 的两个排列 \(P\)\(Q\),现在要取出若干张牌,满足 \(1 \sim n\) 至少出现在一张选出的牌的正面或反面。问方案数。

数据范围:\(1 \leq n \leq 2 \times 10^5\)

做法

\(P_i\)\(Q_i\) 连一条无向边(\(P_i=Q_i\) 的牌跳过),问题转化为选出若干条边,使得每个点都被覆盖过,由于一个点顶多被两条边覆盖,所以最终形成的一定是若干个不相交的环,依次解决每个环即可。

先给出另一个类似的问题,有 \(n\) 个数,每两个相邻的数至少有一个数被取,问取数的方案数。令 \(F(n)\) 表示 \(n\) 个数时的方案数。转移分两种,选 / 不选第 \(n\) 个数,显然有:

\[F(1) = 0, F(2) = 3, F(3) = 5, F(n) = F(n - 1) + F(n - 2)(n \geq 4) \]

回到原问题,发现原问题等价于每相邻两个边至少有一条边被取,我们设 \(G(n)\) 表示环大小为 \(n\) (编号分别为 \(1 \sim n\))时选边的方案数,转移还是分两种,选 / 不选 \((1, n)\) 这条边,有:

\[G(1) = 0, G(2) = 3, G(3) = 4, G(4) = 7, G(n) = F(n - 1) + F(n - 3)(n \geq 5) \]

分别求出每个环的大小,最后将方案数相乘即可。时间复杂度 \(\mathcal O(n)\)

评测链接

ABC247G

题意

\(n\) 个人,第 \(i\) 个人属于大学 \(A_i\),擅长科目 \(B_i\),有 \(C_i\) 的力量,一个梦之队定义为队伍里不存在大学相同或擅长科目相同的人。\(k\) 是梦之队中最大的可能人数,你要求出 \(k\),以及对于 \(i = 1, 2, \cdots ,k\),分别求出梦之队人数为 \(i\) 时最大的力量和。

数据范围:\(1 \leq n \leq 3 \times 10^4\)\(1 \leq A_i, B_i \leq 150\)\(1 \leq C_i \leq 10^9\)

做法

最大费用最大流。

  1. 将源点 \(s\) 向各个大学 \(A\) 连一条流量为 \(1\),费用为 \(0\) 的边。
  2. 对于每个人,将 \(A_i\)\(B_i\) 连一条流量为 \(1\),费用为 \(C_i\) 的边。
  3. 对于每个科目,向汇点 \(t\) 连一条流量为 \(1\),费用为 \(0\) 的边。

连边之后跑最大费用最大流。可以求出 \(k\) 以及该情况下的最大力量和,但是 " 对于 \(i = 1, 2, \cdots ,k\),分别求出梦之队人数为 \(i\) 时最大的力量和。" 这个不太好求,简单的一个想法是再建一个点 \(t_2\),将 \(t_2\) 当作原先的汇点,再将 \(t_2\) 向真正的汇点 \(t\) 分别连流量为 \(1, 2, \cdots, k\) 费用为 \(0\) 的边,然后依次跑最大费用最大流,但是每次跑都要重新清空数组,感觉复杂度不太正确,实际上,我们只需要依次将 \(t_2\) 向真正的汇点 \(t\) 连流量为 \(1\) 费用为 \(0\) 的边,每连一条,也就对应这人数增加 \(1\),这样做就不需要每次清空数组,考虑到网络流是一个会自己调整的过程,所以正确性显然。

评测链接

ABC248F

题意

有一个 \(2 \times n\) 的网格图,一个点与它相邻的点均有连边,现在要你删去 \(k\) 条边,使得图依旧联通,对于 \(k \in [1,n)\) 都要求出其方案数。

数据范围:\(2 \leq n \leq 3000\)

做法

动态规划。

\(f(i, j, 0 / 1)\) 表示当前做到了前 \(i\) 列,删去了 \(j\) 条边,此时第 \(i\) 列的那两个点是否联通(注意此处是否联通需要保证能通过后面的边使得整张图联通)。

考虑新加入一列所产生的三条边进行转移,有:

\[f(i, j, 1) = f(i - 1, j, 0) + f(i - 1, j, 1) + 3 \times f(i - 1, j - 1, 1) \\ f(i, j, 0) = f(i - 1, j - 1, 0) + 2 \times f(i - 1, j - 2, 1) \]

边界为 \(f(i, 0, 1) = 1, f(2, 1, 1) = 4, f(2, 2, 0) = 3\)

评测链接

ABC248G

题意

给定一棵有 \(n\) 个点的树,其中点有点权,定义 \(C(i, j) = k \times \gcd(a_1, a_2, \cdots, a_k)\) 其中 \(k\) 表示 \(i \to j\) 简单路径上经过的点数,\(a_1, a_2, \cdots, a_k\) 表示其简单路径上的 \(k\) 个点。要求下列式子的值:

\[\sum_{i = 1}^{n - 1} \sum _{j = i + 1}^n C(i, j) \]

数据范围:\(2 \leq n \leq 10^5\)\(1 \leq a_i \leq 10^5\)

做法

考虑把原式子进行转化

\[\sum_{i = 1}^{n - 1} \sum _{j = i + 1}^n C(i, j) = \sum_{i = 1}^{n - 1} \sum _{j = i + 1}^n k \times \gcd(a_1, a_2, \cdots, a_k) = \sum_{g = 1}^{\max \{a_i\}} g \times \operatorname{sum}(g) \]

其中 \(\operatorname {sum}(g)\) 表示 \(\gcd\)\(g\) 的简单路径的路径点数和,发现 \(\gcd\) 不好维护,考虑把 \(\gcd\) 拆掉,考虑到

\[g = \sum_{d | g} \varphi(d) \]

所以原式又可以转化为

\[\sum_{g = 1}^{\max \{a_i\}} g \times \operatorname{sum}(g) = \sum_{d = 1}^{\max\{a_i\}} \varphi(d) \times \operatorname{S}(d) \]

其中 \(\operatorname{S}(d)\) 表示 \(\gcd\)\(d\) 的倍数的简单路径的路径点数和。这个就好处理了,先预处理 \(\varphi\) 函数,然后我们枚举 \(d\),将所有点权为 \(d\) 的倍数的点找出来,那么会形成若干个连通块,对于每个连通块我们需要求出其简单路径的路径点数和。考虑树形 dp。

\(\operatorname{siz}(u)\) 表示 \(u\) 的子树大小,\(\operatorname{dep}(u)\) 表示以 \(u\) 为起点,\(u\) 的子树为终点,其简单路径的路径点数和。枚举子树 \(v\) 时将 \(\operatorname{siz}(u) \times \operatorname{dep}(v) + \operatorname{siz}(v) \times \operatorname{dep}(u)\) 加入 \(\operatorname{S}(d)\),其中 \(\operatorname{dep}(u)\)\(\operatorname{siz}(u)\) 表示只处理到 \(v\) 之前的子树。有转移:

\[\operatorname{siz}(v) \to \operatorname{siz}(u) \\ \operatorname{dep}(v) + \operatorname{siz}(v) \to \operatorname{dep}(u) \]

考虑到每个点只有 \(\sqrt{a_i}\) 个因子,所以顶多被枚举到 \(\sqrt{a_i}\) 次,故时间复杂度为 \(\mathcal O(n \sqrt{\max \{a_i\}})\)

评测记录

posted @ 2022-04-29 18:35  chzhc  阅读(20)  评论(0)    收藏  举报
levels of contents