一些题(十七)
[CCO2022] Double Attendance
首先我们可以只在 \(\mathbb{Z}+0.5\) 处操作,这样可以把开区间变成闭区间,且停留一个时刻就算看完了当前 slide。
有一个显然的 dp:记录当前时刻、当前所在教室、此时另一个教室的 slide 是否看过,算这个状态下的最大价值。转移只有两种:等到这个教室的下一张 slide;或是到另一个教室然后等到下一个没看过的 slide。
这样有用的状态是 \(O(n^2)\) 的,转移复杂度 \(O(\log n)\),能过前三个 subtasks。然后发现这个 dp 的值域只有 \(O(n)\) 且关于第一维单调,于是可以交换值域和第一维做到 \(O(n\log n)\)。
https://qoj.ac/submission/36014
[APIO2018] 选圈圈
考虑按题意模拟,设当前要处理的圆半径为 \(r\),需要找到与它相交的所有还没被删的圆。将整个平面分成 \(r\times r\) 的格子,发现只需要对圆心落在以当前圆圆心所在格为中心的 \(5\times 5\) 的网格里的圆依次判断即可,因为还未被删的圆的半径一定 \(\le r\)。
考虑复杂度,在处理所有半径为 \(r\) 的圆的过程中,确定每个圆放在其圆心所在块中是 \(O(n)\) 的(使用 hash 表)。一个圆会被判断的次数至多为圆心落在其圆心所在格周围 \(5\times 5\) 网格中的不交的半径为 \(r\) 的圆的数量,是 \(O(1)\) 的。
考虑减少划分次数,只有当前考虑的圆半径小于当前划分的格子边长的一半时才重新划分,这样只会划分 \(O(\log R)\) 次。而上述复杂度分析的第二部分把 “半径为 \(r\)” 改为 “半径超过当前格子边长的一半” 时仍然成立,所以总复杂度为 \(O(n(\log n+\log R))\)。
https://uoj.ac/submission/559882
[CF1299E] So Mean
就这 *3400?
以下把 \(p\) 当作 \(0,\ldots,n-1\) 的排列。
考虑暴力,每次问 \(n-1\) 个,发现可以 \(n\) 次找到 \(0\) 和 \(n-1\)(但并不能区分这两个),然后 \(n\gets n-2\) 继续做,这样次数是 \(O(n^2)\) 的。
换一种思路,每次问两个,这样能分出奇数和偶数两部分(同样不能区分那个是奇那个是偶)。然后对奇数部分每次问两个,看它们 \(\bmod 4\) 的余数,发现需要拉随便两个偶数部分来凑数,还是可以问出来的,这样就按 \(\bmod 4\) 分成了四个部分。以此类推,就能 \(n\log n\) 次建出一颗从低到高位的 01-trie,但不能区分某个节点的两个儿子。
这样再进行上面那个暴力,发现每问出一个数之后就能把它到根路径上的所有节点的儿子都确定下来,也就缩小了下一次暴力询问的范围。这样至多只会问 \(n\log n\) 次,期望 \(0.5n\log n\) 次。
于是总次数最坏 \(2n\log n\),期望 \(1.5n\log n\),事实上最多只问了 \(9500\) 次,似乎是 CF 上次数最少的(?),没仔细看。
https://codeforces.com/contest/1299/submission/161529379
[CF1685D2] Permutation Weight (Hard Version)
考虑建无向图 \(P=([n],\{(i,p_i)\})\),发现这张图加入边集 \(Q=\{(q_i,p_{q_{i+1}})\}\) 后一定连通。因为边 \((q_i,q_{i+1})\) 会形成一个大环,而 \(q_{i+1}\) 和 \(p_{q_{i+1}}\) 在加了边 \((i,p_i)\) 后在同一个连通块里。
然后发现所有加入后能使 \(P\) 连通的排列形成的图 \(Q\) 都能对应一个合法的 \(q\)。于是要最小化 \(Q\) 的每条边的距离,容易发现下界是 \(2(c-1)\),其中 \(c\) 是 \(P\) 的连通块个数,并且能够取到。
接着要最小化字典序,也就是要判断 \(Q\) 中已有若干边后是否还能取到下界,发现是可以 \(\tilde{O}(n)\) 的,具体条件有点复杂,不想写。
于是就 \(\tilde{O}(n^3)\) 了。
https://codeforces.com/contest/1685/submission/161647118
[CF1608G] Alphabetic Tree
没啥意思。先将所有文本串的所有后缀排序,然后对于每个模式串,可以二分出它在前面那个序列中的位置,比较时可以倍增加哈希。至于 \([l,r]\) 的限制,可以扫描线掉。最后复杂度大概 \(O(q\log^2 n)\)。
[AGC057E] RowCol/ColRow Sort
太神奇了,根本想不到!
https://atcoder.jp/contests/agc057/submissions/32817958
[CF1696H] Maximum Product?
就这 *3500?
https://codeforces.com/contest/1696/submission/162190166
[CF1698G] Long Binary String
先把 \(s\) 开头的 0 先去掉,最后答案加上这些 0 的个数。然后把 \(s\) 看成一个 \(\mathbb F_2\) 上多项式 \(F(x)=\sum_{i\ge 0} s_i x^i\),就是要求最小的 \(k\) 使得 \(x^k\equiv 1 \pmod F\),直接 BSGS 可做到 \(\tilde{O}(2^{|s|/2})\)。
https://codeforces.com/contest/1698/submission/162294158
[ARC144E] GCD of Path Weights
首先只保留从 \(1\) 能到的且能到 \(n\) 的点。然后如果有不经过 \(-1\) 点的从 \(1\) 到 \(n\) 的链,最后将答案和这个链长取 gcd。
把每个点拆成入点和出点,将点权化为边权。然后问题转化为找到最大的 \(y\) 使得存在一种方案将每个拆完后的点赋一个点权,满足对每条边 \((u,v,w)\) 有 \(x_u+w\equiv x_v \pmod y\)。发现这个条件就等价于 \(y\) 能整除任意回路的权值和(可反走有向边,边权取相反数)。于是 dfs 求出它们的 gcd 即可。
https://atcoder.jp/contests/arc144/submissions/33352464
[ARC141F] Well-defined Abbreviation
感觉思路挺自然的。
考虑简化这个集合,如果有两个串满足 \(S\) 是 \(T\) 的子串,那么若 \(T\) 不能被集合中除 \(T\) 之外的串删完,\(T\) 就是 bad 的;否则,\(T\) 就能从集合中删去,因为它已经可以被代替了。
于是集合中剩下的元素互不包含。然后看看什么时候还有 bad 串:如果有两个串满足 \(S=A+B,T=B+C(A\neq C)\) 那么 \(A+B+C\) 就是 bad 的。这个条件看起来就很充要,写一发就过了,不想证明了。
判断这些条件都可以在 AC 自动机上完成。