// 鼠标点击特效 //

Educational Codeforces Round 173 (Rated for Div. 2)

upd:2024/12/18 更新了 G

A

硬币肯定是能拆则拆。时间复杂度 \(O(T\log_{4}n)\)

B

分类讨论 \(5\) 个奇数:

  • 对于 \(1\) ,肯定可以整除。
  • 对于 \(3\) ,可以整除 \(n\) 要求 \(n\) 的数位之和为 \(3\) 的倍数。也就是 \(dn!\equiv 0 \pmod{3}\) 。发现当 \(n \geq 3\) 的时候,\(n!\) 已经是 \(3\) 的倍数肯定满足条件。如果 \(n <3\) ,直接计算是否是 \(3\) 的倍数即可。
  • 对于 \(5\) ,要求 \(d=5\)
  • 对于 \(7\) ,发现 \(111111\)\(7\) 的倍数,也就是说一旦 \(n!\)\(6\) 的倍数也就是 \(n \geq 3\) ,那么肯定满足条件。如果 \(n<3\) ,直接计算是否是 \(7\) 的倍数即可。
  • 对于 \(9\) ,做法类似于 \(3\)
    时间复杂度 \(O(T)\)

C

假设全部的数字都满足 \(a_i \in \{-1,1\}\) ,此时的答案可以取哪些数?

求出最大,最小子段和(可以为空),设他们的值分别为 \(mn,mx\) 。可以证明的是,答案可以取遍 \([mn,mx]\) 之间的任何数。证明:

  • 取最大子段和的全部前缀(可空),至少可以取遍 \([0,mx]\) 之间的任何数。

  • 取最小子段和的全部前缀(可空),至少可以取遍 \([mn,0]\) 之间的任何数。

现在加入 \(a_p \neq \{-1,1\}\) 。那么对于 \(a[1 \dots,p-1]\)\(a[ p+1\dots,n]\) 的答案都可以通过上述算法解决。

剩下的就是那些 \(l \leq p \leq r\) 的区间了。我们求出包含 \(p\) 的最大子段和 \(mx\) 和最小子段和 \(mn\) ,那么答案也可以取遍 \([mn,mx]\) 之间的任何数,证明类似。求的具体方法就是求出 \(a_{p-1}\) 结尾的最大/最小后缀和 \(a_{p+1}\) 开头的最大/最小前缀和。

将满足条件的数排序并去重即可。时间复杂度 \(O(Tn \log n)\)

D

求出一个极大的区间 \([x,y]\) 满足 \(l \leq xG \leq yG \leq r\) 。接下来问题转化为了找到两个值 \(p,q \in [x,y]\)\(\gcd(p,q)=1\) ,最大化 \(|p-q|\)

直接猜 \(p\in [x,y]\cap [x+\log y] ,q \in [x,y] \cap [y-\log y,y]\) 然后过了。时间复杂度 \(O(T \log^3 V)\)

(bro把 \(\log\)\(40\) 然后赛后被hack了,但是开到 \(64\) 即可通过)

E

这个题目很好!

首先二进制问题是可以拆位的,问题转化为了01矩阵问题。我们可以进行的操作有:行涂 \(0\) ,列涂 \(1\) ,问矩阵 \(A\) 是否可以变成矩阵 \(B\) ?

假设不考虑 \(A\) 的状态,仅考虑 \(B_{i,j}\) 的状态:

  • \(B_{i,j}=1\) ,那么第 \(i\) 行涂 \(0\) 应该在第 \(j\) 列涂 \(1\) 之前操作。

  • \(B_{i,j}=0\) ,那么第 \(i\) 行涂 \(0\) 应该在第 \(j\) 列涂 \(1\) 之后操作。

如果将上述关系连边,最终是一个 DAG 就有解。这真的对吗?

我们发现错误原因在于认为每一行,每一列都操作,但是这是不对的。我们引入一个超级源点,连向哪些必要操作的点(\(A_{i,j} \neq B_{i,j}\)):

  • \(A_{i,j}=0,B_{i,j}=1\) ,则必须进行列涂 \(1\) ,源点向其连边。

  • \(A_{i,j}=1,B_{i,j}=0\) ,则必须进行行涂 \(0\) ,源点向其连边。

仅考虑超级源点可以到达的点构成的导出子图,如果是一个 DAG 就有解。现在很对。

对于每一个二进制位都判断以下,时间复杂度 \(O(n^2 \log V)\)

F

动态dp题,出的很烂。问题取反面:选取不为空的,尽量小的集合使得异或和为 \(0\)

考虑问题放到线段树上,每一个节点维护 \(f_i\) 表示异或和为 \(i\) 的最小节点数,\(g_i\) 表示可以到达最小节点数的方案数。容易在 \(O(\log^2 V)\) 的时间内合并两个节点。

则直接使用线段树来做,预处理 \(O(n \log^2 V)\) ,查询 \(O(q \log n\log^2 V)\) ,无法通过。

考虑猫树分治,预处理是 \(O(n \log n \log V)\) ,查询 \(O(q \log^2 V)\)

G

这个题目的做法很有参考价值!

我们考虑分块去做。将答案拆分为块内的答案和块外的答案。只要维护了 \(sum_{i,j}\) 表示元素 \(i\) 在前 \(j\) 个块中出现的次数,配合一个桶很容易去以 \(O(\frac{n}{B})\) 的时间去计算块外的答案(在已知块内答案的基础上),其中 \(B\) 是块长。

对于块内的问题,我们考虑直接维护数组 \(f_{i,j}\) 表示第 \(i\) 个块到第 \(j\) 个块的答案。可以直接以 \(O(\frac{n^2}{B})\) 的时间暴力预处理,考虑点修对 \(f\) 的影响:转化为减少某一个元素/添加某一个元素。这里拿添加元素举例。

假设添加元素 \(v\) 的下标所在块是第 \(x\) 个块,则对于 \(i \leq x \leq j\)\(f_{i,j}\) 的权值应该增加 \(sum_{v,j}-sum_{v,i-1}\) ,蛮力维护的时间为 \(O(\frac{n^2}{B^2})\) ;我们还需要维护 \(sum\) 本身的变化,直接蛮力维护时间复杂度为 \(O(B)\)

现在分析一下时间复杂度,预处理为 \(O(\frac{n^2}{B})\) 。对于询问,如果是点修,时间复杂度为 \(O(B+\frac{n^2}{B^2})\) ;区间查询时 \(O(B)\) 。发现取 \(B=n^{\frac{2}{3}}\) 时最优秀的,时间复杂度来到了 \(O(Qn^{\frac{2}{3}})\)

但是很遗憾,这是无法通过的。

我们想一下哪里不优的?明明两种询问的操作次数可以被视为相同,但是在点修时,维护 \(f\) 花了 \(O(\frac{n^2}{B^2})\) 的时间,而在查询时,只花费了 \(O(1)\) 的时间去调用 \(f\)

考虑将 \(f_{i,j}\) 增加 \(sum_{v,j}-sum_{v,i-1}\) 转化为增加 \((sum_{v,j}-sum_{v,x})+(sum_{v,x}-sum_{v,i-1})\) .前后部分分别维护,拿前半部分举例,我们枚举 \(j\) ,对于一个相同的 \(j\)\(f_{i \leq x,j}\) 都需要增加 \(sum_{v,j}-sum_{v,x}\) ,直接将贡献打在差分数组上。查询的时候暴力计算差分数组的前缀和,因为差分数组只有 \(O(\frac{n}{B})\) 这么大。

至此,点修的时间复杂度被优化到 \(O(B+\frac{n}{B})\) ;区间查询的时间复杂度变慢了,是 \(O(B+\frac{n}{B})\) 。容易看出 \(B=\sqrt n\) 时最优,时间复杂度为 \(O(Q \sqrt n)\)

posted @ 2024-12-25 01:26  dan-da-dan  阅读(694)  评论(7)    收藏  举报