团队作业选记
全记太累了,太水的不记了,主要是蒟蒻懒。
about sqrt DS
P5046 [Ynoi2019 模拟赛] Yuno loves sqrt technology I
- 区间逆序对数模板,能支持 \(\mathcal O(n \sqrt n)\) 空间。
套路题,考虑区间查询的散 + 整 + 散,逆序对有哪些贡献。
- 整整逆序对。
- 散内逆序对。
- 散整逆序对。
- 散散逆序对。
考虑依次维护。
- 整整逆序对直接求比较困难,记 \(ni_{i ,j}\) 为块 \([i ,j]\) 的逆序对数量,考虑递推,得到 \(ni_{i ,j} = ni_{i ,j - 1} + ni_{i + 1 ,j} + ?\),前面包含了 \([i ,j - 1]\) 的逆序对数量,后面包含了 \([i + 1 ,j]\) 的逆序对数量,发现 \([i + 1 ,j - 1]\) 的逆序对数量多算了,\(i ,j\) 两个整块的逆序对数量没算,因此 \(? = \operatorname{calc}(i ,j) - ni_{i + 1 ,j - 1}\),\(\operatorname{calc}(i ,j)\) 可以提前对块内排序然后归并解决。排序 \(\mathcal O(\frac{n}{B} \times B \log B) = \mathcal O(n \log B)\),归并 \(\mathcal O(B)\),求 \(ni_{i ,j}\) \(\mathcal O(\left(\frac{n}{B}\right)^2 \times B) = \mathcal O(\frac{n^2}{B})\),查询 \(\mathcal O(1)\)。
- 散内逆序对直接 BIT 求解即可,预处理 \(\mathcal O(n \log n)\),查询 \(\mathcal O(1)\)。
- 散整逆序对分两个,散左 + 整 / 整 + 散右。以【散左 + 整】为例,对于散左里每一个元素 \(k\),等价于计算整块内 \([1 ,k - 1]\) 的数量,用桶 \(pre_{i ,j}\) 表示前 \(i\) 个块有多少个 \([1 ,j]\) 元素即可。预处理桶 \(\mathcal O(\frac{n^2}{B})\),查询 \(\mathcal O(B)\)。
- 散散逆序对,把散左和散右分别排序然后归并即可。
- 查询时排序,\(\mathcal O(B \log B)\),有 \(Q\) 次询问,有点不优。
- 预处理时排序,记录每个点的下标即可。预处理 \(\mathcal O(n \log B)\)(和上面的整整一起排了),查询 \(\mathcal O(B)\)。
综上,时间复杂度为 \(\mathcal O(n \log B + \frac{n^2}{B} + QB)\) 的算法,取 \(B = \sqrt{n}\) 可以做到时间 \(\mathcal O(n \sqrt n)\),空间也是 \(\mathcal O(n \sqrt n)\)。
P4887 【模板】莫队二次离线 / 第十四分块(前体)
- 莫队二离板子,没有想象的难,耐心点即可学会。
记 \(f([ql ,qr] ,[l ,r])\) 为 \([ql ,qr]\) 对 \([l ,r]\) 的贡献,莫队二离一般要快速求 \(f([x ,x] ,[1 ,x - 1])\) 以及 \(f([1 ,x] ,[l ,r])\)。
第一个好求,枚举 \(x\),由 \(a_j \oplus a_i = x \Leftrightarrow a_i = x\oplus a_j\) 可以快速求解。
第二个就是所谓的第二次离线,前缀 \([1 ,x]\) 排序,由于 \([l ,r]\) 移动量是普通莫队指针移动量为 \(\mathcal O(n \sqrt n)\)(二离常识),所以可以暴力求解 \([l ,r]\)。
P5047 [Ynoi2019 模拟赛] Yuno loves sqrt technology II
待补。
P4168 [Violet] 蒲公英 & P13984 数列分块入门 9
- 求区间众数模板。
仍然套路题,考虑区间查询的散 + 整 + 散,众数的所有可能。
- 整整众数。
- 散内众数。
考虑依次维护。
- 整整众数依然可以 \(z_{i ,j}\) 表示块 \([i ,j]\) 的众数,显然 \(z_{i ,j}\) 可能的值为 \(z_{i ,j - 1}\) 以及【块 \(j\) 内的元素】,开个桶维护每个数出现次数,两个指针扫。预处理 \(\mathcal O(\frac{n^2}{B^2})\),查询 \(\mathcal O(1)\)。
- 散内众数,依次对散块内的每个数 \(x\) 考虑一下是否可能是答案,维护散块内每个数的出现次数 \(cnt_x\),以及整块内每个数 \(x\) 出现次数,用桶维护,和上面逆序对类似的前缀和。预处理 \(\mathcal O(\frac{n^2}{B})\),查询 \(\mathcal O(B)\),空间复杂度 \(\mathcal O(\frac{n^2}{B})\)。
对于查询调用整整即为 \(z_{bl + 1 ,br - 1}\)。
综上,我们有了时间复杂度 \(\mathcal O(\frac{n^2}{B} + QB)\),取 \(B = \sqrt{n}\),时间复杂度 \(\mathcal O((n + Q)\sqrt n)\),空间 \(\mathcal O(n \sqrt n)\)。
P5048 [Ynoi2019 模拟赛] Yuno loves sqrt technology III
上题但是空间限制变小。
哎不对,这题不用求区间众数,只用求区间众数的出现次数!
那么我们预处理 \(z_{i ,j}\) 为块 \([i ,j]\) 众数出现次数,考虑一次查询散块元素也就 \(\mathcal O(B)\) 个,众数出现次数的取值范围为 \([ans \gets z_{bl + 1 ,br - 1} ,z_{bl + 1, br - 1} + 2B]\)。
考虑依然枚举散块元素 \(x\),我们有两种方法:
-
找到 \(x\) 最右边且不超过 \(r\) 的元素,计算中间 \(x\) 的数量和 \(ans\) 打擂台。发现用
vector维护很好,但是要二分,多了一只 \(\log\)。 -
但是 \(ans\) 有取值范围,也就是 \(ans\) 最多增加 \(2B\) 次,只要判断从 \(x\) 开始(包括 \(x\))的第 \(ans\) 个是否在 \(r\) 前,是就 \(ans \gets ans + 1\) 即可(注意这里要用
while哦)。
元素 \(x\) 在 vector 里的位置要二分?实则不用,预处理 \(pos_i\) 即可,容易 \(\mathcal O(n)\)。
综上,有一个 \(\mathcal O(\frac{n^2}{B^2} + QB)\) 的算法,依旧 \(B = \sqrt n\)。
about STL
- 尽量写
if(mp.count( ... )) ... mp[ ... ],否则如果...位置不存在map会开一个...。 - 尽量不用
unordered_map,它不稳定。 - 还有一些其他的……
P12763 [POI 2018 R2] 诗集 Book of poetry
显然让 \(a_i \gets (a_i + 1) \mod s\),那么题目转化为:
构造一个顺序,记 \(pre_i = \sum\limits_{k = j + 1}^i a_k \mod s\),其中 \(j\) 为上一个满足 \(pre_j = s - 1\) 的下标,如果没有 \(j = 0\),最小化 \(pre_i = s - 1\) 的数量。
考虑贪心,如果存在一个数使得 \(pre_{i} \neq s - 1\) 就填这个数,但是显然这个数不能乱填,我们考虑填剩余次数最多的那个数 \(x\)。
特别地,如果 \(x\) 会使得 \(pre_{i} = s - 1\),那我们填出现次数第二多的,显然这个不会使得 \(pre_i = s - 1\)。
维护每个数的出现次数以及数值,插入 set 容易维护,注意细节。
最后一个特判:去除 \(pre_n = s - 1\)。
具体贪心正确性蒟蒻不会证。
P14511 [NFLSPC #8] 轨道交通
- 总结:要大胆猜测结论。
猜测答案一定为 \(0\)。
每次选择能匹配的直接匹配,如果 \([l ,r]\) 能匹配直接清空 \([l ,r]\) 的,重新匹配新的。
由于一种颜色只有 \(2\) 个端点,维护 \(fir_i ,sec_i\),那么清空操作即为 \(fir_i \gets 0\)。
about 计算几何
P4293 [WC2010] 能量场
-
拆括号,转化为几何问题。
-
凸包 & 旋转卡壳应用。
考虑拆开计算柿子,为 \(m_ac_am_b-m_bc_bm_a\),于是令向量 \(\overrightarrow{a_i} = (m_ic_i ,m_i)\),那么贡献即为 \(\overrightarrow{a} \times \overrightarrow{b}\)。
考虑第一问,转化为几何意义,叉积结果的绝对值即为向量 \(\overrightarrow{a} ,\overrightarrow{b}\) 围成的平行四边形面积,可以除以二变成三角形面积。
考虑如果叉积出来是负数,根据 \(\overrightarrow{a} \times \overrightarrow{b} = -\overrightarrow{b} \times \overrightarrow{a}\),交换两者即可,本质是叉积结果绝对值的最大值,也就是围成平行四边形的面积的最大值。
发现所求显然在凸包上,Andrew + 旋转卡壳即可。
但是要正着和反着旋转卡壳两次,因为凸包上固定向量 \(\overrightarrow{i}\),逆时针找到一个向量 \(\overrightarrow{j}\) 的叉积应该是先正从小到大,然后负从小到大,但是绝对值加了就可能是先大后小。容易发现正反两次可以避免这个问题。
考虑第二问,几何意义就是围成凸多边形的面积的最大值的两倍,凸包即可。
about 串串
不偏向计数类。
CF1320D Reachable Strings
- 挖掘性质,寻找不变量,如奇偶、相对顺序等。
考虑一次变换会改变什么,不改变什么。
容易发现中间的 1 不变,好像没用;旁边的 0..1 交换位置。
发现只有一个 \(0\),且交换后 0 的奇偶位置不变。
显然/手玩会发现 0 的相对位置不变。
因此题意转化为:
给定两个以 \(l_1 ,l_2\) 开头的字符串,判断 \(0\) 的个数是否相同,并且每个 \(0\) 的出现位置奇偶性是否相同,分别以 \(l_1 ,l_2\) 为初始下标(即为 \(1\))。
手玩一下发现是对的,严谨证明略,感觉略微显然。
然后这个可以对 \(0\) 的位置奇偶性进行 hash,奇数为 \(1 + x\),偶数为 \(0 + x\),\(x\) 是我们定义的常数,用来减小冲突(其实 \(x = 0\) 也可以)。
我们定 \(has_{i ,0/1}\) 为起点是偶/奇时的 hash 值,对于 \(2\mid i\) 的位置 \(i\) 能对 \(h_{i ,0}\) 产生贡献,对于 $2\nmid i $ 的位置 \(i\) 能对 \(h_{i ,1}\) 产生贡献。
然后用区间 hash 判断一下每组询问,这题就做完了。
AT_arc151_e [ARC151E] Keep Being Substring
- 分类讨论和图论建模,包括样例也很重要。
下文把数当成字符。
手玩两个样例,第一个样例有解释,我们发现如果 \(x ,y\) 存在公共子串,设长度为 \(k\),那么可以把 \(x\) 删到只留下这个长 \(k\) 的子串,然后添加 \(y\) 中的非该子串的字符。
最少需要为 \(\lvert x\rvert + \lvert y \rvert - 2k\),这是显然的,也容易证明每一步都合法。我们需要最大的 \(k\) 为 \(k_{max}\),即求两个字符串的最长公共子串,Hash + 二分/SAM 均可。
如果 \(k_{max} = 0\),考虑我们刚才的做法是先删后加,这样会把 \(x\) 清空,不合法。
一种思路是把 \(x\) 加到存在和 \(y\) 有公共子串的时候再删和加,容易发现长度为 \(1\) 必然不劣。
由于最后我们要删除 \(\lvert x \rvert - 1\) 个字符,留下这个共有字符,我们不妨先删除 \(x\) 到只有一个字符,这样左边右边都能扩展,肯定不劣于刚才的做法。
也即是说我们要对于 \(x\) 中的每一个字符 \(b\),找到一个属于 \(y\) 中的字符 \(c\)(添加操作),然后删除除了 \(c\) 的字符,最后添加 \(y\) 中非 \(c\) 字符。
假设离 \(b\) 左边或者右边最近的字符 \(c\) 离 \(b\) 的距离为 \(k\),那么显然要 \(\lvert x \rvert - 1 + k + k + \lvert y \rvert - 1 = \lvert x \rvert + \lvert y \rvert + 2k - 2\) 步。
容易发现添加只关系到相邻的字符,我们对 \(a_i \xrightarrow{cost = 1} a_{i + 1}\) 建图,那么等价于一个多源 dij 问题。
然后我们找到最小的 \(d\),答案即为 \(\lvert x \rvert + \lvert y \rvert + 2d - 2\)
由于 \(d\ge 1\),所以这种方法劣于存在公共子串的方法,因此做法不存在问题。
CF1080E Sonya and Matrix Beauty
- trick:子矩阵计数可以考虑枚举左右界拍扁成 \(n\) 行 \(r - l + 1\) 列,然后用什么线性/单 log 的算法计数。
本题就是这样。
先不考虑列,考虑行怎么样,行能重排成回文当且仅当:
- 列长为偶数,每个字符出现次数都是偶数。
- 列长为奇数,每个字符出现次数最多只有一个奇数。
然后考虑列,假设拍扁的矩阵只有 \(k\) 行。
- 如果我们排完了第 \(1\) 行,那么第 \(k\) 行必须和第 \(1\) 行相等。
- 如果我们排完了第 \(2\) 行,那么第 \(k -1\) 行必须和第 \(2\) 行相等。
- ……
也就是这些对应行的【字符出现次数数组】必须相同,直接 hash 即可。
然后就是回文问题,manacher 即可。
注意如果不合法需要断开,但是我们有更简单的方法,直接将 hash 值赋值成互不相同的不在 \([0 ,mod - 1]\) 内的整数即可实现断开。
about constructive algorithms
构造水平一坨。
常用 trick:
- 弱化限制。
- 强化限制。
- 特殊性质。
- 答案上下界。
- 外围排除法。
- 等等。
CF1485D Multiples and Power Differences
考虑弱化限制,没有 \(a_{i ,j} \mid b_{i ,j} ,b_{i ,j} \ge 1\) 的限制。
对于网格图,黑白染色是个常见的思路。
于是可以构造:
考虑加上 \(a_{i ,j} \mid b_{i ,j}\) 的限制(令 \(a \mid 0\)),可以构造:
考虑加上 \(b_{i ,j} \ge 0\) 的限制,我们只要加上一个数 \(c = \operatorname{lcm}(1 ,2 ,3 ,\dots ,15 ,16)\) 即可,即:
正确性显然。
CF1667C Half Queen Cover
发现是构造最优解,考虑答案下界,并尝试构造到答案下界。
令最少摆放 \(k\) 个半皇后,先不考虑对角线,钦定它们放在前 \(k\) 行前 \(k\) 列,因为完全可以平移格子。
考虑上对角线,那么剩下的右下角 \((n - k) \times (n - k)\) 只有可能被对角线先覆盖。
\((n - k) \times (n - k)\) 的棋盘有 \(2(n - k) - 1\) 条对角线,因此满足 \(k\ge 2(n - k) - 1\),解得 $k \ge \lceil \frac{2n - 1}{3} \rceil = \lfloor \frac{2n + 1}{3} \rfloor $。
考虑构造,在 \((1 ,1)\) 放置一个半皇后,然后第二行可以放在 \((2 ,3)\),放 \((2 ,2)\) 肯定不优,两者覆盖了右下角棋盘的同一个对角线。
当列 \(> k\) 时把列改为 \(2\),然后 $4 ,6 ,8\dots $ 即可。
可以证明这是正确的,数量恰好为下界(右下角棋盘的对角线仅被一个半皇后覆盖)。
CF1158B The minimal unique substring
注意力?
考虑加强限制,猜测存在构造方案是一个无 border 串不断循环(可以不是整循环)。
注意力惊人,想到这个可能是发现样例有循环节,然后弱化一下循环节无 border。
假设循环节长度为 \(p\),对于最短唯一子串的长度恰好为 \(k\),等价于:对于长 \(i \in [1 ,k - 1]\) 所有子串并非唯一子串,但是对于长 \(k\) 的子串存在唯一子串。
由于循环串无 border,那么对于一个长度为 $j < k $ 的子串,只能通过位移 \(\pm p\) 位得到另一个相同的子串。
- \(j < k\):对于所有子串的起始位置 \(i\),都有 \(i - p \ge 1\) 或者 \(i + p - 1 + j \le n\),即 $ p \le \max (i - 1 ,n - i - j + 1 \ge n - i + 1 - (k - 1) = n - i - k + 2 )$。当 \(i - 1 = n - i - k + 2\) 限制最紧,\(i = \frac{n - k + 3}{2}\),但是此时 \(i\) 不为整数,故 \(i = \frac{n - k + 2}{2}\),代入得到 \(p \le \frac{n - k + 2}{2} ,2p \le n - k + 2\)。
- \(j = k\):只要存在 \(i\) 使得 \(i - p < 1\) 并且 \(i + k - 1 + p > n\) 即可,得 \(\max\{i - 1 ,n - i - k + 1\}< p\),由于存在只要有一个满足要求的 \(p\) 即可,限制最宽 \(i - 1 = n - i - k + 1 ,i = \frac{n - k + 2}{2}\),代入得 \(p > \frac{n - k}{2} ,2p > n - k\)。
因此 \(p = \frac{n - k + 2}{2}\),然后只要构造一个长它的无 border 串然后循环即可。
AT_agc064_b [AGC064B] Red and Blue Spanning Tree
比较显然的构造,但我还是不会/ll。
对于一条边 \((u ,v ,w)\) 满足 \(a_u = w ,a_v = w\) 的边,我们一次可以满足两个端点的要求,贪心地就选上。
然后是对于一条边 \((u ,v ,w)\) 满足 \(a_u = w\) 或 \(a_v = w\),一次可以满足一个端点的要求,贪心地选上。注意这里选边应该是从第一类选上的节点开始,BFS 添加,否则不能保证你随便添加的是基于当前情况下优秀的。
最后把剩下的选上,就是凑齐树边。
如果最后还是不能使所有端点都满足条件,或者图不连通,那么输出 No。
本文来自博客园,作者:2021zjhs005,转载请注明原文链接:https://www.cnblogs.com/2021zjhs005/p/19828582

浙公网安备 33010602011771号