一些题(十六)
[2017 山东三轮集训 Day1] Fiend
题目相当于求 \(\det\{[j\in[L_i,R_i]]\}_{n\times n}\)。先对每行做一次差分,那么一行要么是只有一个 \(1\) 在 \(R\) 处(如果这行的 \(L=1\)),要么在 \(L-1\) 处有一个 \(-1\) 且在 \(R\) 处有一个 \(1\)。对于第二种行,连一条 \((L-1,R)\) 的无向边,此时如果这些边成环了,说明环边代表的行的集合的和为零向量,最后行列式为 \(0\)。否则可以根据建成的森林确定出唯一一个贡献行列式的排列并求出答案。
[AGC055F] Creative Splitting
https://atcoder.jp/contests/agc055/submissions/31813262
[CF1466I] The Riddle of the Sphinx
https://codeforces.com/contest/1466/submission/160794866
[AT Xmas Contest 2020 D] Determinant
先把所有列做一个向下差分,然后发现这个矩阵有值的位置只有 \(O(n\log n)\) 个位于上三角区域的以及最底下一行,这样直接消元就可以做到 \(O(n\log n)\)。
然后感性理解一下消元的过程,可以建出一个 DAG(特判掉 \(C=1\) 的情况):
- \(0\) 向 \(1,\ldots,n-1\) 连边权为 \(C\) 的边,向 \(n\) 连边权为 \(1\) 的边。
- 连边 \((i,i+1,1/(1-C)),(i,ki,C/(1-C)),(i,k(i+1),-C/(1-C)\),其中 \(i\ge 1,k\ge 1\)。
那么答案就是从 \(0\) 到 \(n\) 的所有路径权值乘积的和再乘上 \((C-1)^{n-1}\)。
再观察一下这些路径,发现对于 \(k>1\),若走了 \(i\rightarrow k(i+1)\),会有另一条 \(i\rightarrow i+1\rightarrow k(i+1)\) 去抵消它,反之亦然。那么可以只考虑从 \(0\) 走出去后先走若干条 \((i,ki,C/(1-C)\) 的边然后走 \((i,i+1,1)\) 直到 \(n\) 的路径。
列出式子,发现可以用类似杜教筛的方法 \(\tilde{O}(n^{2/3})\) 求出。
https://atcoder.jp/contests/xmascon20/submissions/31810440
[gym102056E] Immortal … Universe
首先发现合法当且仅当不存在两个串的各一个前缀使得它们的和 \(\le 0\) 且这两个前缀的下一个字符为 P
或结尾(但不能同时为结尾)。于是可以分别算出每个串的满足上述要求的最小前缀和为 \(x\) 以及是否只在末尾取到的方案数,倒着 dp 即可做到 \(O(n^2)\)。
https://codeforces.com/gym/102056/submission/157541068
[gym101981C] Cherry and Chocolate
容易发现最优策略一定是:A 先选一个节点删除,B 选择一个剩下连通块的重心,A 再选这个重心的重儿子。那么 A 就想最小化连通块去掉重儿子后的节点数。
考虑求出每个子树的重心,以及去掉每个子树后的重心。前者是经典的 \(O(n)\) 树形 dp。对于后者,可以考虑以整棵树的重心为根,这样去掉一个根的轻子树中的子树后重心会往重儿子跑,可以先 \(O(n)\) 求出删掉的子树大小为 \(i\) 是重心会跑到哪里。而去掉根的重子树的子树后重心会先往次重儿子跑然后一直走重儿子,可以类似的做。
https://codeforces.com/gym/101981/submission/157535855
[gym101981H] Huge Discount
考虑对一个给定串怎么求它能消剩下的最小数:
- 如果存在一个数字出现次数过半,那么最优一定是把除了它的数都消完(一定可行);
- 否则如果串长是偶数则一定能消完;
- 如果是奇数则会剩下一个,可以枚举剩的位置,合法当且仅当它左右两边都可以消完。
考虑对从后往前依次所有后缀求出答案,前两种情况都可以预处理后 \(O(1)\) 判断。第三种情况的限制则形如三维偏序,然后 \(O(n^3/w)\) 的 bitset 过了,更科学的做法是发现这三维偏序至多一维不满足,就可以改为用树状数组做到 \(O(n\log n)\)。
[gym101981L] Lagrange the Chef
以下将除了 X,Y 的数称作 O。所求即为保留原序列的一个最长子序列使得未保留的数任意插入后能使新序列合法。首先特判掉无解以及仅保留 X 或 Y 的情况(一定会保留所有 X/Y)。于是未保留的 X 一定可以插入在被保留的 X 旁边,Y 同理。而 O 则需要插入在被保留序列中连续出现的 XY 中间(如果存在的话),所以合法当且仅当前者数量多于后者。那么可以 dp,记录两者数量之差以及一些辅助变量即可做到 \(O(n^2)\)。
https://codeforces.com/gym/101981/submission/157622203
[AGC057F] Reflection
手玩了 2h 找到规律了,太有意思了!!!
https://atcoder.jp/contests/agc057/submissions/31948532
[BalticOI2022] Uplifting Excursion
不妨设所有物品重量和 \(\ge L\),否则可以把重量和 \(L\) 全部取反。
然后考虑贪心地构造一个方案:先全选上所有负数,然后从小到大依次选每个正数直到选完后总和超过 \(L\),记这样选出来的集合为 \(S\),那么 \(S\) 中元素和在 \([L-M,L]\) 中。
接下来需要调整 \(S\) 使得其中元素之和恰为 \(L\) 且元素个数尽量多。
有两种调整操作:选一个不在 \(S\) 中的元素加入或将一个 \(S\) 中的元素移出。由于每个元素的范围为 \([-M,M]\),所以一定有一种调整方法使得每时每刻 \(S\) 中元素和在 \([L-M,L+M]\) 中。
而同时如果这个元素和在不同的时刻取到了相同的值,那么这两个时刻之间的调整都可以不做。因为初始时 \(S\) 中的元素均小于等于不在 \(S\) 中的元素且所有负数均在 \(S\) 中,所以这些调整做完后元素个数不可能变多。
于是调整只会进行 \(O(M)\) 次,所以对于 \(S\) 和 \(S\) 的补集分别做一次值域 \(O(M^2)\) 的背包即可知道最优的调整方案。
时间复杂度 \(O(M^3)\)。
[北大集训2021] 魔塔 OL
如果怪物集合确定,那么就是一个经典问题:按照某种顺序排序然后求前缀 min。这题要求在四维偏序中求这个问题,考虑四毛子。先将所有怪物按顺序排序,然后每 \(B\) 块考虑。先 \(O(2^B)\) 预处理出每个子集的前缀 min 和总和的二元组,然后对于每个询问求出这一块中那个子集包含在这个询问的四维偏序里,就可以将预处理的二元组合并到这个询问之前的二元组里。时间复杂度 \(O((2^B+n)n/B)\) 取 \(B=O(\log n)\) 得 \(O(n^2/\log n)\)。