十月训练记录

\(CF643G\)

考虑 \(50\%\)的情况 , 每次取出两个不相同的数将它们删除 , 那么最后得到的必然是绝对众数。

这个做法显然可以扩展到任意比例的情况 , 只需要将操作改成 "取出 \(K\) 个并删除" 即可。

可以用线段树维护。

时间复杂度 : \(O(C(N + Q)logN)\)\(C = 100\)

\(CF1083D\)

对于区间 \([b , c)\) , 记 \(pre_{i}\) 表示 \(a_{i}\) 出现在左边第一个的位置 , \(suf_{i}\) 表示 \(a_{i}\) 出现在右边第一个的位置。

那么其贡献就是 \((b - max\{pre\})(min\{nxt\} - c)\)

枚举右端点 \(c\) , 单调栈 + 线段树维护即可。

时间复杂度 : \(O(NlogN)\)

\(CF1172F\)

观察 \(sum\) 函数 , 发现其输出必然是输入值减去了若干个 \(p\)

考虑一个 \(O(N \sqrt{NlogN})\) 的做法 , 首先将序列分块 , 定义函数 \(F(i , x)\) 表示权值为 \(x\) , 输入到第 \(i\) 个块中 , 最后的输

出值是多少 , 这个函数可以在 \(O(B ^ 2)\) 的时间内预处理出。 回答询问只需在块内查询即可。

考虑优化这个做法 , 首先观察发现 , \(x - F(x)\) 这个函数是单调不降的 , 也就是说 , \((x + 1)\) 一定比 \(x\) 减去的值更多。

接着 , 可以通过归纳法证明 , \(x - F(x)\) 这个分段函数至多是 \((l + 1)\) 段。

因此 , 建出线段树 , 对于线段树上每个区间求出分段函数 , 合并两个分段函数的时候用 \(two - pointers\) 扫描。

查询时 , 只需在线段树分成的 \(O(logN)\) 个区间内二分即可。

时间复杂度 : \(O(Qlog^2N)\)

\(CF896E\)

首先将序列分块。 用链表 \(f_{i , x}\) 表示第 \(i\) 块中权值为 \(x\) 的数字集合。

对于操作 , 如果值域比 \(2x\) 大 , 就将 \([1..x]\) 内的数向上合并 , 否则将 \([x + 1..max]\) 向下合并。

对于询问 , 直接求链表长度即可 , 可以通过并查集维护。

定义一个区间的势能为其极差 , 不难发现这样的做法在 \(O(x)\) 的时间内使得一个块的势能减小了 \(x\)

故时间复杂度 : \(O((N + Q)\sqrt{N})\) (值域与 \(N\) 同阶)

\(CF1083F\)

首先考虑最朴素的做法 : 从小到大枚举 , 遇到不同的就翻转。

定义差分序列 \(c_{i} = a_{i} \oplus b_{i} \oplus a_{i - 1} \oplus b_{i - 1}\) , 那么每次操作只修改了 \(c_{i}\) 的两个位置。

因为每次影响到的两个数在模 \(K\) 意义下相同 , 故可以将序列按下标值模 \(K\) 分组。

对于一组而言 , 其答案为前缀异或和非零的数的个数 , 其理由在于 : 一个前缀异或值为 \(0\) 的数必然将答案减小了 \(1\)

考虑根号分治。 当 \(k \geq \sqrt{N}\) 时 , 每次直接暴力修改 , 否则 , 将序列分为若干块 , 对每块打上整体标记并维护块内每个数的出现次

数即可。

时间复杂度 : \(O((N + Q)\sqrt{N})\)

\(LOJ 3366\)

来源于国际信息学竞赛 \(2020\)

首先一个显然的结论是 , 游戏负责人必然会选择玩家抽到数字中的中位数 , 因为这会使其收益最小化。

因此 , 这等价于每次选出的 \(K\) 个数中 , 有 \(\frac{N}{2}\) 个贡献为 \(1\) , 而其余的贡献均为 \(-1\)。 最大化贡献之和。

继续将这个问题进行转化 , 其等价于 : 每行选出 \(K\) 个数 , 在所有选出的 \(NK\) 个数中选择一半贡献为正 , 另一半贡献为负。 求出最大的总和。

可以用调整法证明只要找到一组解这组解就合法。

那么这个问题就很容易了 , 只需用一个堆每次贪心取贡献最大的二元组就可以了。

时间复杂度 : \(O(NKlogK)\)

\(LOJ3365\)

来源于国际信息学竞赛 \(2020\)

首先如果存在 \(p_{i , j} \geq 3\) , 那么必然无解。 因为这样必然存在两点满足其不同的路径数超过 \(3\) 条。

对于 \(p_{i , j} = 0\) 的情况 , 相当于将这张图分割成若干联通分量。

对于剩下的点集 , 用链 + 环构造即可。 需要用并查集维护。

时间复杂度 : \(O(N\alpha(N))\)

\(Day 8 - Day14\)

\(CF1396E\)

首先 , 对于每一条边 , 记其贡献为 \(c_{e}\)。 设这条边将树分成两部分大小分别为 \(x_{e}\)\(y_{e}\) , 令 \(z_{e} = \min(x_{e} , y_{e})\)。 则 :

\(1\) : 至少有 \(z_{e} \mod 2\) 个点经过 \(e\)

\(2\) : 至多有 \(z_{e}\) 个点经过 \(e\)

综上 , 有 \(z_{e} \mod 2 \leq c_{e} \leq z_{e}\) , 因此得到 : \(\sum_{e}{(z_{e} \mod 2)} \leq S(f) \leq \sum_{e}{z_{e}}\)

\(S(f) = \frac{1}{2} \sum_{i}{depth_{i} + depth_{f_{i}} - 2 \cdot depth_{lca(i , f_{i})}}\)。 与 \(\sum_{e}{z_{e}}\)\(2\) 意义下同余。

至此 , 得到了有解的一个必要条件。 也就是 \(\sum_{e}{(z_{e} \mod 2)} \leq S(f) \leq \sum_{e}{z_{e}}\)\(S(f)\)\(\sum_{e}{z_{e}}\)\(2\) 同余。

接着考虑证明这个条件同样是充分的。

不妨记 \(L(T) = \sum_{e}{(z_{e} \mod 2)}\) , \(R(T) = \sum_{e}{z_{e}}\) 并取树的重心 \(G\) 为根建树。

约定 \(size(u)\) 表示以 \(u\) 为根的子树大小 , \(depth(u)\) 表示 \(u\) 节点的深度。

考虑数学归纳法 :

\(N = 2\) 时 , 树的形态只有 \(1\) 种 , 显然成立。

\(N = 2M - 2\) 时成立 , 考虑 \(N = 2M\) 的情况 :

\(K = R(T)\) 时 , 由树重心的性质 , 直接将 \(DFS\) 序上 \(i\) 号节点向 \(i + \frac{N}{2}\) 节点连边即可。

否则 , 取 \(G\) 的儿子节点 \(g\) , 使得 \(size(g)\) 最大。 取节点 \(w\)\(g\) 中深度最大且 \(size(w) \leq 2\) 的节点。

\(K + 2 \cdot depth(u) \leq R(T)\) , 若 \(w\)\(2\) 个儿子 , 直接将这两个儿子匹配 , 否则将 \(w\) 和其仅有的儿子节点匹配。 不难发现问题转化为 \(N = 2M - 2\)\(L'(T) \leq K' \leq R'(T)\) 的情况。并且由树重心的性质 , 删去这两个点后树的重心仍然是 \(G\)。 继续递归构造即可。

否则 , 子树 \(g\) 中必然存在一点使得 \(K + 2 \cdot depth(u) = R(T)\)。 找到这个点并与其任意一个儿子节点匹配。 问题就转化为了 \(K = R(T)\) 时的情况。

用平衡树维护这个过程 , 时间复杂度 : \(O(NlogN)\)

\(CF1422F\)

首先讲讲我的做法 :

考虑若干个数的最小公倍数 , 本质是对每个质因子指数取最大值。

发现值域并不大 , 因此可以分为不超过 \(\sqrt{val}\) 和超过 \(\sqrt{val}\) 分别考虑。对于超过 \(\sqrt{val}\) 的质因子最多只有 \(1\) 个 , 可以用可持久化线段树维护。 而不超过 \(\sqrt{val}\) 的质因子数量并不多。 因此只需维护约为 \(\frac{\sqrt{val}}{log(val)}\) 棵支持查询区间最值的线段树即可。 时间复杂度 : \(O(?)\)

事实上存在更加优秀的做法 : 不妨枚举质因子的次幂 , 记 \(pre_{i}\) 表示上次出现 \(i\) 这个数是在哪个位置 , 那么只需在当前位置去除上个位置的影响 , 并加入新的数的影响即可。 可以用 \(1\) 棵可持久化线段树维护。

时间复杂度 : \(O(NlogN)\)

\(CF1167F\)

考虑 \(a_{i}\) 的贡献 , 为 \((n - i + 1) \cdot \sum_{j = 1}^{i - 1}{[a_{j} < a_{i}] \cdot j} + i \cdot \sum_{j = i + 1}^{n}{[a_{j} < a_{i}] \cdot (n - j + 1)}\)

这是个二维偏序 , 可以用树状数组维护。 时间复杂度 : \(O(NlogN)\)

\(CF1254D\)

对于每个修改操作 , 令根节点为 \(v\)。 那么 \(u\) 被加 \(d\) 当且仅当 \(u\)\(r\) 不在同一棵子树中 , 其概率为 \(\frac{n - size(u)}{n}\)

考虑树上差分并用树状数组维护。 但每个点的儿子最多有 \(O(N)\) 个。

处理这样的情况有一个常用的方法 , 对树进行轻重链路径剖分 , 在修改时只修改重儿子 , 并维护轻儿子的信息。

时间复杂度 : \(O(Nlog^2N)\)

\(CF1416D\)

考虑离线 , 倒着处理修改操作 , 此时删除操作相当于加边并且构成树形结构。

建出这棵重构树。 并用 \(DFS\) 序 + 线段树维护子树最值即可。

时间复杂度 : \(O(NlogN)\)

\(10\)\(13\) 日训练

现场得分 : \(0 + 30 + 100 = 130\)

\(A\)

容易发现矩阵的秩就是答案。时间复杂度 : \(O(N ^ 3)\)

对精度的处理不当会导致得到 \(0\) 分的成绩。 \(EPS\) 最好设成 \(10^{-3}\)

\(B\)

首先用 \(Pollard-Rho\) 算法对 \(val_{1}\) 做质因数分解。 并通过其质因子求出其所有的因子 (不超过 \(2 ^ {15}\)个)。

考虑一种朴素的动态规划做法 : 记 \(f_{i}\) 表示节点 \(i\) 的答案 ,将 \(val_{1}\) 的因子标号 , 并记 \(g_{i}\) 表示权值对应标号为 \(i\) 的节点的 \(f\)
值总和。 \(f\) 的值可以通过 \(g\) 来求出 , 而 \(g\) 的值可以在 \(DFS\) 时的时候顺带维护。 这个做法的复杂度是 \(O(N \cdot 2^M)\) 的(取 \(M = 15\))。

注意到 \(2 ^ {15}\) 这个数非常特殊 , 且查询的复杂度远低于修改的复杂度 , 于是考虑平衡规划 , 记 \(h_{i , j}\) 表示上一次选择的数前 \(7\) 位为 \(i\) , 后 \(8\) 位为 \(j\) 的方案数。 那么复杂度就优化到了 \(O(N \cdot 2^{\frac{M}{2}})\)

事实上在这题中质因数分解并不需要用 \(Pollard - Rho\) 算法。 只需先找出 \(10 ^ 7\) 以内的质因子 , 去除这些质因子 , 将剩下的数和其他的数求最大公约数即可。 如果没有找到 , 那么无论剩下的数是否是质数都是无关紧要的。

\(C\)

考虑容斥原理。 答案为 :

\(三个点的总贡献 - 至少有一条边的贡献 + 至少有两条边的贡献 - 三元环的贡献\)

其正确性在于 : 对于任意三个互相之间没有边的点 , 在这个式子中被计算了 \(1\) 次。
对于任意三个互相之间有一条边的点 , 在这个式子中被计算 \(1 - 1 = 0\) 次。
对于任意三个互相之间有两条边的点 , 在这个式子中被计算了 \(1 - 2 + 1 = 0\) 次。
对于一个三元环 , 被计算了 \(1 - 3 + 3 - 1 = 0\) 次。

故只有符合要求的情况被统计到答案中。

总贡献 , 至少一条边的贡献和两条边的贡献都是很好处理的。

而三元环的贡献可以通过这篇文章中的技巧做到 \(O(N \sqrt{N})\) : 链接

时间复杂度 : \(O(N \sqrt{N})\) , 需要注意细节的实现。

\(10\)\(14\) 日训练

现场得分 : \(100 + 60 + 40 = 200\)

\(A\)

\(dp_{i}\) 表示第 \(i\) 天为晴天的概率。

根据期望的线性性将每天的贡献求和即可。

\(B\)

首先考虑一个最简单的矩阵 , 将 \(1\)\(NM\) 从大到小填入其中。

如何从这个最简单的矩阵推出收益最大的矩阵呢?

一种很优的贪心方式是 : 从最后一行最后一列开始依次扫描 , 将当前数尽可能变大。 这样可以做到 \(O(M ^ 2)\)

考虑加速这个过程 , 首先算出最多能将多少行加到满。 然后最多只需要对剩下的两行进行上述贪心即可。 时间复杂度 :\(O(M)\)

\(C\)

考虑建出笛卡尔树。

对于一组询问 , 找出其 \(LCA\) , 答案即为 : 从 \(LCA\) 走到 \(L\) 向左走的次数 + 从 \(LCA\) 走到 \(R\) 向右走的次数 + 1。

离线 \(Tarjan\) / \(ST\) 表预处理 \(LCA\) 即可。

时间复杂度 : \(O(MlogN)\)

\(CF1430D\)

首先将 \(0\)\(1\) 的连续段合并。

考虑删除数时让两个连续段合并必然不优 , 因此对于每个位置向后找到第一个大于 \(1\) 的段即可 , 可以用一个指针扫描。

时间复杂度 : \(O(N)\)

\(CF1430G\)

考虑记 \(dp_{S}\) 表示剩余点集为 \(S\) 的答案。

枚举一个集合将它们标号 , 计算其贡献并转移即可。 要用高维前缀和预处理答案。

时间复杂度 : \(O(3 ^ N)\)

事实上这题还可以做到 \(O(Poly(N))\) , 对于每个点建 \(N\) 个对应权值的点 , 那么求最小割即可。

\(CF1408G\)

考虑一个点集合法的条件是形成了一个团。 否则一定是不行的。

因此只需建出 \(Kruskal\) 重构树 , 在树上做背包即可。

时间复杂度 : \(O(N ^ 2)\)

\(CF568C\)

首先判断是否可行是个经典的 \(2 - SAT\) 问题。

考虑深度优先搜索构造方案 , 事实上在这题上搜索的复杂度只有 \(O(N)\) , 用一个 \(std :: bitset\) 维护不可行的点即可。

时间复杂度 : \(O(\frac{N ^ 3}{w})\) (取 \(w = 32\))

\(CF1381C\)

首先考虑 \(X = 0\) 的情况。 即要求 \(A\) 中和 \(B\) 中有 \(Y\) 个元素相同 , 但必须错位排列。 当 \(Y = N\) 时 , 问题转化为广义错排问题。 即要求出现次数最多元素不超过 \(\frac{N}{2}\)。 而对于 \(Y < N\) 的情况 , 依然按照 \(Y = N\) 时的构造方式做一遍 , 设 \(B\) 与构造出的数组有相同元素的下标为 \(K\) , 并设 \(f\)\(B\) 中出现次数最多的元素个数。

那么有 : \(K = \max(f - \lfloor {\frac{N}{2}} \rfloor , 0)\)

注意到一定有一个元素满足 \(1 \leq e \leq N + 1\) , 且该元素未在 \(b\) 序列中出现。 因此可以将这个数填充到 \(k\) 个相等的位置中。

因此当且仅当 \(K \leq N - Y\) 时成立。

现在考虑 \(X \neq 0\) 的情况。 有一个显然的贪心策略 : 每次取出现次数最多的并将其替换为 \(e\)。 那么用堆维护即可。

时间复杂度 : \(O(NlogN)\)

\(CF1387B1\)

考虑一棵子树只会对其父节点贡献 \(0 / 1\) 个点。

那么直接构造就行了。

时间复杂度 : \(O(NlogN)\)

\(CF1387B2\)

\(x_{e} , y_{e}\) 分别表示删去边 \(e\) 后的两个联通块大小。

考虑答案的上界 , 为 :

\(\sum_{e}{min\{x_{e} , y_{e}\} \cdot 2w_{e}}\)

取树的重心 \(G\) , 那么根据重心的性质 , 其每个儿子节点的 \(size\) 值不超过 \(\lfloor \frac{N}{2} \rfloor\)。故直接用广义错排问题中的构造方式构造即可。 这样答案可以取到上界。

事实上并不需要取树的重心 , 只需以任意节点为根就行了 , 因为假设两个在 \(DFS\) 序中距离为 \(\frac{N}{2}\) 的节点在 \(G\) 对应的儿子的同一子树中 , 这个子树的大小就超过了 \(\frac{N}{2}\)。与重心的性质矛盾。

时间复杂度 : \(O(N)\)

\(AGC018D\)

如果重心在边上 , 答案为 \(S - w\)

否则答案为 \(S - min\{e_{i}\}\)

正确性可以构造证明。

时间复杂度 : \(O(N)\)

\(CF571D\)

首先将询问和操作离线。

根据前两种操作 , 可以建出两棵重构树 \(T1 , T2\)

运用树状数组上二分 , 在 \(T2\) 上求出每个节点最后一次被清零是什么时候。

再在 \(T1\) 上求出询问的答案即可。

时间复杂度 :\(O(QlogN)\)

\(CF582D\)

考虑 \(p ^ \alpha | {n \choose m}\), 记 \(v_{p}(n)\) 表示 \(n\)\(p\) 的指数是多少。

显然 , \(v_{p}(n) = \sum_{k}{\lfloor \frac{N}{p ^ k} \rfloor}\)

那么一对二元组 \((n , m)\) 满足要求当且仅当 \(v_{p}(n!) - v_{p}(m!) - v_{p}((n - m)!) \geq \alpha\)

下取整很难化简 , 但注意到 \(\lfloor \frac{n}{p ^ k} \rfloor = \frac{n - n \mod p ^ k}{p ^ k}\)

于是得到 :

\(原式 = \frac{m \mod p ^ k + (n - m) \mod p ^ k - n \mod p^k}{p ^ k}\)

观察后发现如果 \(p\) 进制下 \((n - m)\) 产生一个进位 , 则 \(p\) 因子数多了 \(1\)

于是问题转化为了一个经典的数位动态规划模型。

时间复杂度 : \(O(N ^ 2)\)

\(CF582E\)

首先建出表达式树 , 表达式树的好处在于可以通过子树信息合并得出根结点的信息。

\(f_{i , S}\) 表示根结点为 \(i\) , 带入等式后得到的式子为 \(S\) 的方案数。

转移可以用 \(FWT\) 合并。

时间复杂度 : \(O(N2 ^ N)\)

\(2020\) 正睿十连测第六测 :

\(A\)

双指针即可。
时间复杂度 : \(O(N)\)

\(B\)

首先将正数和负数分开做。

考虑全是正数的情况 , 维护一个堆 , 初始时将二元组 \((1 , 0)\) 放入堆中 , 每次取出堆顶 , 将 \((s + a_{i + 1} , i + 1) , (s - a_{i} + a_{i + 1} , i + 1)\) 加入堆中。 这样的空间复杂度是 \(O(KlogK)\) 的。

做完这部分后 , 对每个正数维护一个负数指针 , 再用一个堆维护即可。

时间复杂度 : \(O((N + K)logK)\)

\(C\)

记有 \(w\) 行有车 , \(h\) 列有车 , 那么一个答案即为 \(mw + hn - wh\)

因此要求的就是 \([l1 , r1]\) 中有多少个 \(i\) 满足有一个 \(i\) 第二维出现在了区间 \([l2 , r2]\) 中。

对第一维莫队 , 第二维分块即可。

时间复杂度 : \(O(N \sqrt{N}log(N))\)

\(2020\) 正睿十连测第五测 :

\(A\)

首先 \(K = 0\) 的情况就是判定是否每个点的度数都为偶数。

考虑一个图求线图后 , 每条边在新图中的度数是 \(deg_{u} + deg_{v} - 2\)

若给定的图的 \(K\) 阶线图是欧拉图 , 那么 \((K - 1)\) 阶线图必然每个点的度数都奇偶性相同。

接着 , 若 \(K\) 阶线图的度数奇偶性相同 , 将 \((K - 1)\) 阶线图奇数度数的点放在左侧 , 偶数的点放在右侧 , 那么这张图必然是二分图。 而二分图不可能是任何图的线图。

综上得到了判定的方法 , 但具体实现还需考虑一条链的情况 , 因为一条 包含 \(K\) 个点的链求 \(K\) 次线图最终必然会成为一个点。

时间复杂度 :\(O(N \alpha(N))\)

\(B\)

考虑容斥原理 , 两个矩形相交的条件为 :

发现这些贡献是二维偏序。 考虑整体二分 , 每次用树状数组求二维偏序即可。

时间复杂度 : \(O((N + M)log^2N)\)

\(2019\) 正睿十连测第四测

\(C\)

第一个性质是 , \(Y\) 值一定是前几步增加都是 \(0\) , 而后面增加的都非零。 这是因为如果后面部分有一步增加的是 \(0\) , 那么交换到前面一部分必然更优。

第二个性质是 , \(Y\) 在增加非零阶段时 , 必然是按照 \(a\) 值从大到小排列 , 这是因为若存在 \(a_{i} < a_{i + 1}\) , 那么交换会更优。

注意到增加为零的阶段可以任意排列 , 不放将序列按 \(a\) 值为关键字从小到大排序 , 设 \(dp_{i , j , k}\) 表示前 \(i\) 个数 , 现在 \(x\) 值为 \(p\) , 增加为 \(0\) 的阶段 \(a\) 值至少是 \(q\) 的最大收益。

直接做是 \(O(NX ^ 2)\) 的。 但发现每个 \(dp_{i , p , q}\) 只会转移到 \(dp_{i , p - a_{i} , q}\)\(dp_{i , p , q - a_{i}}\)。 有 \(p + q = X - \sum_{j \leq i}{a_{j}}\)

因此有效的 \((p , q)\) 只有 \(O(X)\) 个 , 这样复杂度就被优化到 \(O(NX)\)

\(2019\) 正睿十连测第八测

\(B\)

考虑如何唯一表示一个状态 , 记 \(dp_{i , S}\) 表示取了前 \(i\) 个 数 , \(S\) 是一个二进制状态 , 第 \(i\) 位表示的是表示当前字符串是否可能是 \(B\) 串的前 \(i\) 位和 \(A\) 串的前 \((i - j)\) 位拼合而成。

预处理转移即可。

注意到数据随机 , 因此可以把状态压缩起来用 \(std :: map\) 存储 , 最大数据的运行时间不超过 \(5ms\)

\(C\)

根据抽屉原理 , 离一个点距离最近的点距离为 \(1\) , 最远为 \(2N - 1\) , 因此当 \(M \geq 2N - 1\) 时 , 每个点都能找到。 直接输出即可。

否则考虑两个点对哪些区域产生贡献 :

\(1\)). \((x1 , y1)\)\((x2 , y2)\) 构成对角线 , 有三块区域(用蓝色标出)

\(2\)). \((x1 , y1)\)\((x2 , y2)\) 不构成对角线 , 同样有三块区域(用蓝色标出)

维护三个差分数组即可。

时间复杂度 : \(O(N ^ 2 + M ^ 2)\)

\(2019\) 江苏省队集训 第五天

\(C\)

看到 \(r\) 互不相同的情况可能具有启发意义 , 首先思考如果有这个条件该怎么做。

考虑一个贪心做法 , 将线段按左端点为关键字排序 , 依次考虑每个区间 , 采用尽可能向后拖延的策略 , 当有一个需求将要过期时 , 将它和前一段未过期的需求放在一起处理掉。 这个做法的可以用扫描线 + 平衡树维护。

接着考虑有右端点相同的情况。 考虑改造数据 , 将右端点相同改成右端点不同 , 且不影响最终的答案。 直接做有些麻烦 , 考虑所有右端点都相同的情况 , 那么将左端点从小到大排序 , 贪心地用最小的左端点配最小的左端点 , 次小的左端点配次小的右端点 ,.... , 最大的左端点配最大的右端点。 显然这样是最优的 , 可以用堆维护。 那么将线段按颜色为第一关键字 , 右端点为第二关键字从小到大排序 , 对于一段连续的颜色相同且右端点相同的套用上面的做法 , 就解决了这个问题。

至此将右端点相同转化为了右端点不同 , 那么用右端点不同的做法解决即可。

具体实现较为繁琐。

时间复杂度 : \(O(NlogN)\)

国庆模拟赛 第一天

\(C\)

看到奇数想到异或 , 但直接做显然是不行的 , 所以首先对每种数随机一个 \(2 ^ {64}\) 以内的权值。 那么一段区间中每个数出现次数为奇数就可以近似表示为这段区间的权值异或值为 \(0\) , 可以证明 , 发生冲突的概率是很小的。

考虑对每个位置记个 \(pre\) , 表示这个权值上次出现是什么时候。

每次对右端点维护每个左端点区间的异或值 , 相当于每次将 \([1 , pre)\) 这段区间异或了一个数 , 并支持查询全局 \(0\) 的个数。

用线段树这样的带 \(log\) 数据结构维护显然是不行的 , 考虑分块 , 每一块维护一个整体标记和一个哈希表即可。

时间复杂度 : \(O(N \sqrt{N})\)

国庆模拟赛 第二天

\(C\)

首先考虑忽略 \(OR\) 的操作 , 维护全局异或标记并用可持久化字典树维护即可。

考虑有 \(OR\) 的操作 , 不妨维护两个标记 \(OR\)\(XOR\) , 那么每个数的实际值就是 \((X | OR) \oplus XOR\)

\(XOR\) 标记还是直接维护 , 而对于每次 \(OR\) 操作 , 不妨将 \(XOR\)\(OR\)\(1\) 的位变为 \(0\) , 并将 \(OR\) 或上 \(x\)。 如果 \(OR\) 标记的值发生改变那么就暴力重构可持久化字典树。

因为 \(OR\) 标记最多变化 \(O(log(N))\) 次 , 故总时间复杂度 : \(O(Nlog^2(N))\)

国庆模拟赛 第四天

\(A\)

不难发现 \(Alice\) 的策略是固定的。将 \(a\) 值为第一关键字 , \(b\) 值为第二关键字排序即可。

\(Bob\) 在前 \(N\) 个数中最多只能取 \(\lfloor \frac{N}{2} \rfloor\) 个 , 考虑已经维护出了前 \((N - 1)\) 天的最优解并将 \(Bob\) 取的数放入一个堆中 , 那么对于新的一天只需考虑取当前的是否比堆顶优即可。

时间复杂度 : \(O(NlogN)\)

\(B\)

一般情况下考虑的都是曼哈顿距离转切比雪夫距离 , 但在这题中需要考虑切比雪夫距离转化曼哈顿距离。

线段树 + 扫描线即可。

时间复杂度 : \(O(NlogN)\)

\(C\)

首先需要二分答案。

一个性质是 : 一个点最多被两个区间覆盖 , 因为如果被三个区间覆盖必然有一个区间无用。 根据这个性质就可以动态规划了。

进一步地 , 用线段树维护这个动态规划即可。

时间复杂度 : \(O(Nlog^2N)\)

\(CF848C\)

将每个数映射到平面上的一个点 \((i , pre_{i})\)

考虑差分答案 , 显然 , 要求的是一个矩形内数的和。

\(CDQ\) 分治 / 树套树维护即可。

时间复杂度: \(O(Nlog^2(N))\)

\(CF715B\)

首先将所有边权赋为 \(1\)

倒着跑一遍最短路 , 求出 \(disT\)

再正着跑最短路 , 每一条边的权值设成 \(max\{1 , L - disT_{u} - disS_{u} - 1\}\) 即可。

最后再跑最短路检查是否合法即可。

时间复杂度 : \(O(NlogN)\)

\(2020\) 正睿十联测第七测

\(A\)

首先设 \(a < b\)

考虑 \(Kruskal\) 算法的过程 , 首先会先合并权值为 \(a\) 的联通块 , 然后在 \(a\) 边被用完时再用 \(b\) 边。那么不妨将 \(a\) 边联通块合并并进行缩点。

接着 , 考虑怎样的一条路径会出现在一棵最小生成树上 , 显然 , 只要这条路径没有重复经过一个 \(a\) 边构成的联通块 , 就是合法的。

那么就有一个状压 \(DP\) 的做法了 : 设 \(dp_{i , S}\) 表示现在在 \(i\) , 已经经过的 \(a\) 联通块集合为 \(S\) 的最短路径。

这样可以拿到 \(53\) 分的分数。

考虑一个不超过 \(3\) 个点的 \(a\) 联通块 , 因为从这个联通块走两条 \(b\) 边再走回来一定比直接在联通块内走优 , 所以将这些联通块压缩起来是不必要的。 因此时间复杂度就被优化到了 : \(O(2 ^ {\frac{N}{4}}M)\) , 可以得到满分。

\(B\)

首先对于一个限制 , 符合要求的点构成了一个树上联通块。 而要做的就是判定这个树上联通块是否有交并输出任意一个点。

显然每个树上联通块都有一个最浅的点 , 不妨称其为 “代表点”。

结论 : 这些联通块有交当且仅当所有的“代表点”中最深的那个点 \(x\) 符合要求。

证明 : 假设有一个联通块没有覆盖 \(x\) 。 那么有两种可能的情况。 一种是这个联通块完全在 \(x\) 子树内 , 另一种是这个联通块完全在 \(x\) 子树外。 如果全部在子树内 , 那么 \(x\) 一定不是最深的 , 矛盾。 如果是全部在子树外 , 因为 \(x\) 所在的联通块都在 \(x\) 的子树内 , 因此这两个联通块必然没有交 , 无解。

时间复杂度 : \(O(N)\)

\(C\)

首先考虑一个 \(O(N ^ 3)\) 的做法 : 将 \(a\) 从大到小排序 , 由最小的 \(a_{i}\) 向前分组 , 设 \(dp_{i , j}\) 表示前 \(i\) 个数还剩 \(j\) 个的方案数。 转移要用一些组合数的技巧。

直接用 \(FFT\) 优化就可以通过了 , 但这样的做法不优美。

一个常用的优化技巧是 : 设 \(dp_{i , j}\) 表示前 \(i\) 种权值 , 还剩 \(j\) 个的方案数。 这样的复杂度就是 : \(O(N ^ 2log(N))\) (调和级数)

\(CF1436E\)

首先求出 \([1 , 1] , [1 , 2] ... [1 , i] ... [1 , n]\) 区间的 \(mex\) 值。 显然这些 \(mex\) 是单调递增的。

从前往后考虑每一个数 \(a_{i}\) , 先求出这个数离最近的一个相等的数的位置 \(nxt\) , 用线段树二分求出 \([i + 1 , nxt]\) 中第一个 \(mex\) 值比 \(a_{i}\) 大的位置 \(x\) , 那么 \([x , nxt]\) 这段数的 \(mex\) 就变为了 \(a_{i}\) , 在线段树上修改即可。

这个过程顺带求出了原序列中所有出现过的子区间的 \(mex\) 值 , 那么将这些数存起来再求一遍 \(mex\) 即可。

时间复杂度 : \(O(NlogN)\)

\(CF1435E\)

首先当 \(a > bc\) 时显然答案为 \(-1\)

一个重要的事实是 : 只用考虑第一个 \(a\) 未被耗尽及其之前的区域。 这是因为如果过期了那么还不如从后面一段开始更优。

如图 , 记 \(k = \frac{a}{bd}\) , 那么答案为 \(a(k + 1) - \frac{k(k + 1)}{2}bd\)

时间复杂度 : \(O(1)\)

\(CF1436F\)

首先考虑去掉第三个条件 , 是个极其经典的莫比乌斯反演 : \([gcd(a_{1} , a_{2} , ... a_{n}) = 1] = \sum_{d | gcd(a_{1} , a_{2} , ... a_{n})}{\mu(d)}\)

这样就只需枚举 \(d\) , 计算序列中 \(d\) 为倍数的数的贡献。乘上莫比乌斯函数后相加即可。

显然对于一个数有两种贡献 , 一种是平方贡献 , 另一种是与其他数的乘积贡献。 对于平方贡献, 其系数为 \(2 ^ {k - 2} \cdot (k - 1)\)。 对于第二种贡献 , 其系数为 \(2 ^ {k - 3} + (k - 2)2 ^ {k - 2}\)。分别计算即可。

时间复杂度 : \(O(N\sqrt{N})\)

\(CF1421E\)

首先注意到最后每个数的贡献要么是 \(1\) , 要么是 \(-1\)

结论 : 记序列长度为 \(N\) , 负号个数为 \(M\) , 有 \(N + M \equiv 1(mod\ 3)\)。且可以找到两个相邻的数符号相同。

证明 : 首先证明必要性 , 当 \(N \in [1 , 3]\) 时结论成立。 因为将两个符合条件的序列合并后仍然是一个符合要求的序列 ,所以一个可行解必然满足 \(N + M \equiv 1(mod 3)\)。然后证明充分性 : 枚举最后一步合并的位置 , 将整个序列分裂为两部分, 符号分别取反。 如果一部分满足条件 , 那么另一部分也满足条件。 递归构造即可。不难发现一定能找到一个符合条件的位置。

然后就是一个简单的动态规划问题了。

时间复杂度 : \(O(N)\)

\(CF1437F\)

先将数组 \(a\) 从小到大排序, 对于每个数维护一个指针表示最大的 \(j\) 使得 \(2a_{j} \leq a_{i}\)。 显然一个序列中必然存在一个递增的子序列 , 这个子序列的下标对应着每次前缀最值更新的位置。 不妨对这个序列进行动态规划 , 再动态规划的同时将所有 \(2a_{j} \leq a_{i}\) 的数也加入序列中。

时间复杂度 :\(O(N) 或 O(N ^ 2)\)

\(CF1437G\)

建出原字符串的 \(AC\) 自动机。

答案是 \(AC\) 自动机上一条链的节点在 \(fail\) 树上的权值和。树链剖分 + 线段树维护即可。

时间复杂度 : \(O((N + M)log ^ 2N)\)

\(CF1419E\)

如果只有三个因子, 那么需要额外的一个数。

否则将 \(N\) 质因数分解 , 并构造如下 :

时间复杂度 : \(O(\sqrt{N})\)

\(CF1419F\)

首先二分答案。

将可以互相到达的点用并查集合并。 此时 :

如果联通块数 \(1\) 个 , 显然可行。

如果联通块数 \(2\) 个 , 那么就需在两个联通块中找到两个点 , 使它们添加一个点后联通。

联通块 \(3 , 4\) 个的情况也是容易处理的。

如果超过了 \(4\) 个联通块 , 根据抽屉原理 , 不可行。

时间复杂度 : \(O(N ^ 2logN)\)

\(CF1434D\)

首先最优解的一个端点必然同样是直径的一个端点。

找出直径 , 以两个端点为根 , 维护支持区间翻转的线段树即可。

时间复杂度 : \(O(QlogN)\)

\(CF1310E\)

考虑 \(K = 1\) 的情况 , 要求的是找到 \(b_{1} \geq b_{2} .... \geq b_{m}\)\(\sum{b_{i}} \leq n\)。 直接动态规划。时间复杂度 \(O(N ^ 2)\)

考虑 \(K = 2\) 的情况 , 不难发现一个 \(b\) 序列合法当且仅当有 \(\sum{b_{i}c_{i}} \leq n\)\(c_{i}\) 两两不同。 不妨令 \(b_{1} \geq b_{2} .... \geq b_{m}\) , 贪心地使 \(1\) 匹配 \(b_{1}\)\(2\) 匹配 \(b_{2}\) .... \(m\) 匹配 \(b_{m}\) , 这样必然最优因为如果交换会使得和变得更大。那么问题转化为有多少个 \(b\) 满足 \(b_{1} \geq b_{2} ... \geq b_{n}\)\(\sum{b_{i} \cdot i} \leq N\)。 设 \(dp_{val , j , sum}\) 表示上一个数为 \(val\) , 现在匹配到 \(j\) , 和为 \(sum\) 的方案数。 因为 \(val \cdot j \leq N\) , 所以复杂度是 \(O(N^2log(N))\) 的。

考虑 \(K \geq 3\) 的情况 , 显然一个序列在两次操作后数的个数变为根号级别。 不妨直接暴力搜索 , 这样的复杂度是 \(O(\rho(N))\)

\(CF1314D\)

首先不存在奇环当且仅当黑白染色后每次经过的点颜色交替。

不妨给每个点随机分配颜色然后动态规划求解。

一次随机的正确率为 \(\frac{1}{512}\) 那么随机 \(512 * 20\) 次的正确率超过 \(99.99 \%\)

\(CF1314C\)

考虑比较两个子串的长度 , 显然先求出 \(LCP\) 后就可以做到 \(O(1)\)

考虑二分答案 , 在计算方案数的时候枚举左端点做动态规划 , 由 \(LCP\) 的性质 , 可行的右端点是一段后缀。

因此用后缀和优化这个动态规划。

时间复杂度 : \(O(N ^ 2log(N))\)

\(CF1299D\)

首先图中任意一个环的异或和可以通过若干个简单环异或得到。

注意到本质不同的线性基个数并不多 , 共有 \(374\) 种。 因此可以将其压成最简形式 , 并建立有限状态自动机。

注意线性基要这样写 :

注意到这张图割掉 \(1\) 条边后形成的联通块只有两种可能 : 一种是没有三元环 , 还有一种是有且仅有 \(1\) 个 (如图)。

那么不妨令 \(dp_{i , j}\) 表示考虑了前 \(i\) 个联通块 ,当前在 \(j\) 的方案数。

转移比较简单 , 不赘述了。

时间复杂度 : \(O(374N)\)

posted @ 2020-10-04 20:04  evenbao  阅读(350)  评论(0编辑  收藏  举报