「Log」做题记录 2024.1.1-2024.1.28
\(2024.1.1-2024.1.7\)
\(\color{blueviolet}{P1501}\)
LCT 板子,链加链乘查询链和,断边加边。
\(\color{black}{P4332}\)
LCT 爆踩树剖的非常好题目啊。
将节点分为四种,子节点值为 \(1\) 的个数分别为 \(0/1/2/3\),叶子节点统一视为 \(0/2\)。
考虑一个叶子节点改变时会向上影响一段连续的 \(1/2\),于是考虑维护区间第一个不为 \(1/2\) 的节点编号(splay 内)。
然后修改就相当于 \(1/2\) 的翻转,把需要操作的区间打个标记即可。
\(\color{blueviolet}{P4649}\)
非常仙 DP 题。
题意转化是简单的,求去掉一些非树边使得图中不存在偶环的最小代价。
如果一条边两端点的树上路径长度为奇那么此边必须删掉。
剩余的边会在树上会组成一些奇环,两奇环一旦相交于某条边就会产生一个偶环。
相当于每条非树边会覆盖掉其两端点树上简单路径的树边,要求每条树边至多被选出的非树边覆盖一次。
考虑先全删掉,尽量保留一些代价大的边,对于每条非树边考虑挂在其端点的 LCA 上进行处理。
设 \(f_{i, S}\) 表示节点 \(i\) 子树内,对于 \(\forall x \in S\),都有边 \((i, x)\) 已经被覆盖的状态下得到的最大代价。
对于挂在点 \(i\) 上的一条非树边 \((u, v)\),选择其产生的贡献为 \(w + [u \not= i]f_{u, 0} + [v \not= i]f_{v, 0}, \sum \limits_{x \in (u \to v) \land x \not \in \{u, v, i\}} f_{fa_x, \{x\}}\),\(w\) 为边权,求和部分即去掉链端点和 LCA 的贡献。
对于每一条边都尝试更新一边当前点的 DP 数组,复杂度可以接受。
\(\color{blueviolet}{P3262}\)
深度只有 \(10\) 的完全二叉树,发现一个叶子结点的贡献只跟祖先节点状态有关,DFS 时枚举祖先状态,这样可以得到叶子结点贡献,再用类似背包的转移上去,复杂度主定理分析或者分析每个节点遍历次数都可以得到是 \(O(4^{n - 1}(n - 1))\) 的,可以接受。
状态是 \(f_{i, j}\) 当前枚举的状态下,节点 \(i\) 子树内选择了 \(j\) 个农民去当兵的最大贡献。
\(\color{royalblue}{P3745}\)
平凡题。
不难发现代价只与最晚发布成绩相关,先预处理每个时间发布成绩学生的不愉悦度,然后从后向前枚举最晚成绩发布时间。
计算贡献只要做前缀和,分别尝试只用 \(2\) 操作和尽量用 \(1\) 再用 \(2\) 调整。
\(\color{blueviolet}{P3746}\)
脑子题。
从组合意义上理解,要求的即从 \(nk\) 个物品中选出 \(x\) 个满足 \(x \mod k = r\),然后对这个进行一个 DP,设 \(f_{i, j}\) 表示前 \(i\) 个物品中选出个数余数为 \(j\) 的总方案数。
转移方程为 \(f_{i, j} = f_{i - 1, j} + f_{i - 1, (j - 1 + k) \mod k}\),有初值 \(f_{0, 0} = 1\)。
显然可以用矩阵优化转移,于是就完事了。
\(\color{blueviolet}{P4139}\)
考虑用扩展欧拉定理降幂,发现模数在递归时不断减小,至 \(1\) 时答案一定为 \(0\),递归层数是可以接受的。
预处理 \(\varphi(i)\) 即可。
\(\color{blueviolet}{P3747}\)
磨了好几天可算会了。
参考 P4139,递归进行降幂时最终模数会为 \(1\),这种递归的深度是 \(\log\) 级别的,因为每次偶数的欧拉函数都会至少减半。
也就是说如果一个位置被操作很多次之后,这个位置本来的值 \(a_i\) 会被忽略,再进行操作值也不会变,这个上界就是递归的深度。
对于 \(c\),预处理其 \(10^8\) 以内的光速幂(在不同模数下,模数即上述递归中每次指数的模数)。
对于 \(a_i\),预处理其操作 \(0\) 次到上界之间的所有值,直接递归求解即可。
然后套线段树维护区间和以及最小操作次数即可。
\(\color{blueviolet}{P3748}\)
答辩题。
设 \(f_{i, 0/1/2/3}\),分别表示(均认为节点 \(i \not= 1\) 有一向子树外的连通块):
-
节点 \(i\) 子树内去掉一条以节点 \(i\) 为端点的链得到的最大连通块数量。
-
节点 \(i\) 子树内去掉一条不经过节点 \(i\) 的链得到的最大连通块数量。
-
节点 \(i\) 子树内去掉一条经过 \(i\) 节点的链得到的最大连通块数量。
-
节点 \(i\) 子树内去掉一条以节点 \(i\) 为端点的链,再去掉一条不经过节点 \(i\) 的链得到的最大连通块数量。
转移是繁琐的,过于繁琐了,懒得细说,反正会了。
\(\color{blueviolet}{P3750}\)
不难,但很有质量,我直接大呼好题。
首先最优策略是固定的,显然开着的最高位开关肯定要操作,最优次数从高往低扫一遍即可,而且每个开关不能被别的开关代替。
设 \(f_i\) 表示从还有 \(i\) 个开关需要被操作的状态到还有 \(i - 1\) 个的期望操作次数,根据意义可以列出以下式子:
\(f_i = \frac{i}{n} + \frac{n - i}{n} (f_i + f_{i + 1} + 1)\)
\(\frac{i}{n}\) 即有 \(\frac{i}{n}\) 的概率操作对一个,后半部分即操作错之后要操作回来的期望。
可以当成一个一元一次方程解出 \(f_i\) 的递推式子。
边界状态较为显然 \(f_n = 1\)。
首先最开始求出 \(cnt\) 表示初始状态下需要操作多少次,如果 \(cnt <= k\) 那么 \(cnt\) 就为答案,否则答案为 \(k + \sum \limits_{k< i \le tem} f_i\)。
答案最后要乘以阶乘。
\(\color{blueviolet}{P4363}\)
非常好题目,第一次见这种状压。
每一层不能比上一层多,考虑状压表示轮廓线,从左下到右上 \(0\) 表示横线,\(1\) 表示竖线。
需要从初始状态向后递推,否则最优子结构无法保证,深搜一下即可。
\(\color{blueviolet}{P4364}\)
普通贪心是简单的,可以有 \(55pts\)。
每次把最大合法点拿出来,相等的连续一段从右侧向左取,线段树维护当前点靠左的空位数量,线段树上二分即可。
\(\color{black}{P4365}\)
有线段树+拉插做法,但我不会拉插,所以采用了一种很暴力的求法。
首先假设每个点分别为选出的第 \(k\) 大,那么现在需要知道选出的点钟有的 \(k - 1\) 个比当前点权值大的方案数。
把大于当前点的值都设为 \(1\),小于的设为 \(2\),相等的比较下标。
于是问题转化为对于所有点选出权值总和为 \(k - 1\) 的方案数,显著的做树形背包 \(f_{i, j}\) 表示在第 \(i\) 个点子树内,选出连通块权值和为 \(j\) 的方案数(强制选当前点)。
注意转移,常数很小所以可以跑过。得到一个教训,做背包的时候可以枚举 \(0 \le i \le siz_u, 0 \le j \le siz_v\) 贡献到 \(i + j\),但不可以枚举 \(i + j\) 再枚举 \(j\),这样复杂度是错的。
\(\color{black}{P4382}\)
神仙流题,巨大量级代码。
第一问可以考虑按照排名依次加入人,对与每个人一次一次加入每个志愿的所有老师的边,尝试增广,增广成功说明可以匹配上,否则无法匹配。
第二问显著的二分,将每个前缀拿出来,建当前处理的人的志愿,看合不合法。
思路是明确的,代码是阴间的。
\(\color{blueviolet}{P5283}\)
首先做前缀异或和,转化为两个数异或的前 \(k\) 大值之和(包括一个初始的 \(0\))。
先丢到 Trie 树上,先把每个数的最大异或取出来放到堆里。
每次取堆顶,再把堆顶的下一大值放回堆里。
但这样是有序对,考虑先 \(k \leftarrow 2 \times k\),然后求完答案除以二。
\(\color{black}{P5290}\)
蓝的盆。
快速幂,MR 素数测试,筛莫比乌斯函数,原根。
\(\color{blueviolet}{P5283}\)
考虑一条链,以中间一个点为根如何合并。
将两个链的最大放到一起、次大放到一起,以此类推,然后将每一对的最大值塞到新堆里,不能成对的数也塞进去。
然后树上启发式合并即可,具体来讲,当前子树和正在遍历的子节点子树,如果子节点子树堆更大,就交换两个堆,然后将子节点堆合并到父节点上。
交换两个堆可能不是 \(O(1)\) 的,所以考虑记录 \(id\) 并交换。
\(2024.1.8-2024.1.14\)
\(\color{black}{CF1552G}\)
神仙题。
首先考虑一个转化,如果给出的操作可以对任意一种初始序列排序,当且仅当它可以对任意一种初始的 \(0/1\) 序列排序,证明是简单的。
对于一种初始序列,对于其任意一个数字 \(x\),将小于 \(x\) 的变为 \(0\),大于等于 \(x\) 的变为 \(1\)。如果给出的操作能对如上构造出来的所有 \(0/1\) 序列排序,那么它一定可以对初始序列排序,故上述转化成立。
对于每种初始 \(0/1\) 序列,只要最终能转化为 \(00 \dots 011 \dots 1\) 的形式就合法。
\(n\) 的范围足够小,我们可以状压到 long long 中,但并不能暴力枚举,\(O(2^{n})\) 的复杂度我们是无法接受的。
对于一次排序,我们只关心 \(0/1\) 的个数,而不关心每个位置具体是什么。
举例来说,对于一次涉及到三个位置的排序,当这三个位置分别为 \(011\) 或 \(101\) 或 \(110\) 的时候是等价的,排完序之后都为 \(011\)。
我们考虑依次处理每个操作,对于没固定的位置枚举可能出现的状态,可以理解为对于每个位置在第一次对它进行操作后确定其值。
依然举例来说,初始序列是不确定的,如 \(????\) 的形式。
假设第一次操作处理了位置 \(2, 3, 4\),那么我们将确定这三位的值,于是序列变为 \(?111\) 或 \(?011\) 或 \(?001\) 或 \(?000\)。
也就是说对于当前操作的所有位置中,假设已确定的 \(0\) 有 \(cnt_0\) 个,\(1\) 有 \(cnt_1\) 个,那么这些位置排序后前 \(cnt_0\) 个位置都必须为 \(0\),后 \(cnt_1\) 个位置都必须为 \(1\),中间未确定的地方就可以枚举 \(0, 1\) 分界点来枚举状态了。
当所有操作都处理完之后只需要判断当前状态是否合法即可。
说一些实现细节,设 \(S_i\) 表示第 \(i\) 次操作涉及到的位置集合,\(T_i\) 表示前 \(i\) 次操作涉及到的位置集合。
首先对于最终状态 \(st\) 我们可以 \(O(1)\) 判断是否合法,先将其取反,那么其若合法则变为形如 \(11 \dots 100 \dots 0\) 的状态,加一后可以得到 \(00 \dots 0100 \dots 0\) 的形式,此时只要判断是否只有一个 \(1\) 即可,即 lobit(st) == st
。
对于取 \(cnt_0, cnt_1\) 可以预处理 \(S, T\) 来用位运算 \(O(1)\) 处理。
下面分析一下复杂度,采用了官方题解的证明。
设 \(d_i = |S_i \setminus T_{i - 1}|\),其中 \(A \setminus B\) 即集合减法,可以理解为从 \(A\) 中去掉与 \(B\) 相交的部分。
有复杂度为 \(O(n\prod\limits_{i = 1}^{k} (d_i + 1))\)。
由于 \(\sum \limits_{i = 1}^k (d_i + 1) \le n + k\),由基本不等式可以知道 \(\prod\limits_{i = 1}^{k} (d_i + 1) \le \left(\frac{n + k}{k}\right)^k\)。
故复杂度为 \(O(\left(\frac{n + k}{k}\right)^k)\)。
\(\color{blueviolet}{CF1578K}\)
让你输出方案,所以是大便题。
入手:
\(k = 0\) 时,显然答案为 \(p\),从每个集合里任意选择一个即可构造出方案。
我们定义特殊点对 \((u, v)\),两者之间存在边(不同集合)为“删边”,不存在边(同一集合)为“加边”。
\(2^k\) 看起来像一个比较可行的复杂度,考虑枚举每个删边或者加边的两种状态,我们优先钦定所有删边的状态,然后才到加边。
对于一条删边,其两端点不可能同时存在于答案中,考虑枚举删去哪一个(使得其不可能在答案中)。
对于一条加边,其产生贡献当且仅当本身被选中,并且处于的集合内选择的加边组成了一个团,所以可以枚举此加边是否选中。
答案的计算:
现在考虑每个特殊点对的状态已经确定,如何统计答案。设 \(sum\) 为所有集合内选中的完全图点数总和,\(eptcnt\) 表示集合内部所有点都被删除的集合数量,\(cplcnt\) 表示集合内部选出完全图的集合数量。
集合贡献分为以下三种:
- 删除完的集合无法造成贡献。
- 选出的完全图造成总共 \(sum\) 的贡献。
- 不是以上两种,则每个可以选出任意一个未被删除的点,造成 \(1\) 的贡献。
有答案为 \(sum + p - eptcnt - cplcnt\)。
贡献的计算:
我们期望 \(O(1)\) 统计答案,考虑如何在枚举状态时维护上述变量。
对于一个点,维护 \(avis_i, dvis_i\),分别表示被选中的加边覆盖的次数、被删边删除的次数。这两者只有从 \(0/1\) 之间转换时会造成贡献,但仍需要计数来保证正确性。
对于一个集合,维护 \(acnt_i, dcnt_i, ecnt_i\),分别表示集合内被选中的点数、被删除的点数、被选中的边数。当 \(dcnt_i = siz_i\) 时,会对 \(eptcnt\) 造成贡献;当 \(\frac{dcnt_i\times(dcnt_i - 1)}{2} = ecnt_i\) 时,内部选中了一个合法团,会对 \(sum\) 以及 \(cplcnt\) 造成贡献。
每次维护只要考虑好变量更改顺序,以及贡献的判定,回溯时删除贡献即可。
方案的输出:
假设我们已经知道最优答案以及当时的状态,考虑输出方案。
我们需要重新维护出 \(dvis_i, acnt_i, ecnt_i\) 来判断每一个点是否被加入,我们只要判断此点符合“答案的计算”中三中贡献的哪一点即可。
考虑点 \(i\),设 \(t = s_i\):
- 第一种有 \(dvis_i \not= 0\),不输出。
- 第二种在不满足第一种的情况下,有 \(\frac{dcnt_t\times(dcnt_t - 1)}{2} = ecnt_t\),输出。
- 第三种在不满足前两种的情况下,有其集合中还未有被统计进答案点,输出;若已有集合内的点,不输出。
\(\color{limegreen}{CF1556E}\)
我们并不关心 \(a_i, b_i\) 的值具体是什么,每次询问我们只想让差值为 \(0\),所以设 \(c_i = b_i - a_i\)。
我们操作目的是使一段连续的 \(c_i\) 值都为 \(0\),考虑每次操作都在干什么。选出 \(c\) 一个长度为偶数的子序列,将其奇数项减一,偶数项加一。于是我们发现操作时的 \(\sum c\) 是固定的,所以当 \(\sum \limits_{i = l}^r c_i \not= 0\) 时无解。
上述操作也可看成在 \(c\) 的前缀和数组上选出一系列区间减一,设 \(d_i = \sum \limits_{j = 1}^i c_i\),询问转化为每次操作可以选出区间内若干区间减一,使 \(d_l, d_{l + 1}, \dots , d_r\) 全变为 \(d_{l - 1}\) 的最小操作次数。当其中存在 \(d_i < d_{l - 1}\) 时显然不合法,否则答案为 \(\max\limits_{l \le i \le r}\{d_i - d_{l - 1}\} = \max\limits_{l \le i \le r}\{d_i\} - d_{l - 1}\)。
ST 表维护即可。
\(\color{royalblue}{CF1567E}\)
线段树板子。
\(\color{royalblue}{CF1575H}\)
数据范围提示我们用 \(O(n^3)\) 的算法来解决,这种匹配问题可以考虑放到 ACAM 或者 KMPAM 上,后者本质上是只添加一个字符串的前者。
很明显我们可以把串 \(b\) 的 KMPAM 处理出来在上面跑 DP,具体地讲,需要处理出一个 \(to_{i, j}\) 表示匹配到 \(b\) 的 KMPAM 的状态 \(i\) 时,下一个字符为 \(j\) 时,应该转移到的状态。
当 \(j = b_{i +1}\) 时,有 \(to_{i, j} = i + 1\),否则有 \(to_{i, j} = to_{nex_i, j}\)。
具体求法可以参考 ACAM 求 fail 的过程,我写 KMP 的版本的时候写挂了,所以干脆换成 ACAM 的处理方式处理出了 \(to\) 数组。
接下来考虑 DP,设 \(f_{i, j, k}\) 表示 \(a\) 匹配到第 \(i\) 个字符,当前在 \(b\) 的 \(j\) 状态下,\(b\) 已经完全匹配过 \(k\) 次的最小代价。
我很难知道有哪些 \(to_{p, q} = j\) 所以填表法在第二维上是困难的,所以第二维用刷表法处理,另外第一维是线性的,第三维刷表填表都是可行的,因为只与 \([to_{j, ch} = m]\) 的值有关(\(ch\) 是枚举的 \(a_i\))。
每次 \(f_{i, to_{j, ch}, k +[to_{j, ch} = m]} \leftarrow \min\{f_{i, to_{j, ch}, k +[to_{j, ch} = m]}, f_{i - 1, j, k} + [a_i \not= ch]\}\) 即可。
\(\color{black}{CF1569F}\)
这么牛的题。
数据范围很小,不是搜索就是状压,但实际上这题两个都用到了。
初具人形,入手:
考虑一下纯暴力复杂度,应该是 \(O(n!k^nn)\),蠢得很的复杂度。
我们发现回文串最多用到 \(\frac{n}{2}\) 种字符,所以 \(k\) 种字符可能不全用上。
这启发我们钦定一共用 \(t\) 种字符,再枚举每个点用什么字符,最后对于合法方案数量乘上一个 \(A_k^t\)(从 \(k\) 个字符中选出 \(t\) 个进行排列),换句话说,我们并不关心每个点具体是什么字符。
对于一种用 \(t\) 种字符覆盖 \(n\) 个点的方案(\(t\) 种字符都要出现过),会产生 \(A_k ^t\) 的贡献(\(t > k\) 时为 \(0\))。
合法的覆盖方案指存在一条回文曼哈顿路径。
混沌初开,第一部分枚举:
观察一条曼哈顿路径 \(p_1 \to p_2 \to \dots \to p_n\),如果其所代表的串是一个回文串,那么有 \(ch_{p_1} = ch_{p_n}, ch_{p_2} = ch_{p_{n - 1}} \dots\),其中 \(ch_i\) 表示第 \(i\) 个点上的字符。
所以我们考虑将点分成一对一对的,如 \(\{x_1, y_1\}, \{x_2, y_2\}, \dots, \{x_{\frac{n}{2}}, y_{\frac{n}{2}}\}\),为了保证不重不漏,我们做以下要求:
- 区间 \([1, n]\) 中的每个整数出现且只出现一次。
- 对于 \(i \in [1, \frac{n}{2}]\), 都有 \(x_i < y_i\)。(强制每个数对无序。)
- 对于 \(i \in [1, \frac{n}{2})\),都有 \(x_i < x_{i +1}, y_i < y_{i + 1}\)。(使得数对之间的顺序固定。)
这样的限制也方便我们枚举所有情况,可以考虑如下过程:
- 从所有未被选择过的数中挑选一个最小的作为当前数对的 \(x\)。
- 枚举所有大于 \(x\) 并且未被选择的 \(y\)。
- 重复如上操作直到所有数字都被选择过一次。
这样操作方案数也是好算的,第一次选择有 \(n - 1\) 中,去掉第一次的 \(x, y\) 之后又有 \(n - 3\) 种选择,以此类推,总方案数为 \((n - 1)(n - 3) \dots 2 \times 1 \le 10395\)。
渐入佳境,判断是否存在的合法路径符合上述枚举:
对于已经枚举出的数对序列 \(\{x_1, y_1\}, \{x_2, y_2\}, \dots, \{x_{\frac{n}{2}}, y_{\frac{n}{2}}\}\),我们考虑用状压 DP 去判断是否存在一条曼哈顿路径使得每个 \(x_i, y_i\) 一一对应。
我们考虑从中间向两边依次放置数对,使得其组成一个合法曼哈顿路径。数对数量最多为 \(6\),可以用状压表示其是否放置过。
设 \(f_{i, u, v}\) 表示是否存在满足以下条件的路径:集合 \(i\) 内的数对都放置过了,现在两侧放置的点分别为 \(u, v\)。我们尝试用刷表法解决。
枚举接下来要放置的数对(编号为 \(j\)),设其为 \(tu, tv\),当 \(f_{i, u, v} = 1\),并且存在边 \((u, tu), (v, tv)\)(或者 \((u, tv), (v, tu)\))时,\(f_{i \cup \{j\}, tu, tv} \leftarrow 1\)。
最后只要判断全集时是否存在一个数对放在最外侧使得其 \(f\) 数组值为 \(1\) 即可。
其实上述状态可以优化为两维 \(f_{i, id}\) 表示是否存在满足以下条件的路径:集合 \(i\) 内的数对都放置过了,现在两侧放置的点为 \(x_{id}, y_{id}\)。
但是三维可过,所以就没写优化的版本。三维 DP 的复杂度大概为 \(O(2^{\frac{n}{2}}\times\frac{n^3}{2})\)。
胜利在望,第二部分枚举,给每个点对分配字符:
我们现在已经得到了一个合法点对序列,考虑对每个点对分配颜色,成为一种方案。
按顺序处理每一个点对,我们可以分配一个新种类的字符给它,并将字符种类加一;也可以分配一个曾经出现过的字符给它。
这样每一个点都得到了一种字符,但我们考虑这样处理方案实际上会有重复,给出如下例子:
现有两组合法点对序列 \(\{1, 2\}, \{3, 4\}\) 以及 \(\{1, 3\},\{2, 4\}\),当一共只有 \(1\) 种字符的时候,两个序列都会给出 \(ch = {1, 1, 1, 1}\) 的字符分配方案。
这样一种方案算了多次,我们考虑去重。将字符的分配数组 \(ch\) 转成 vector 放到 set 里,最后统计答案的时候遍历即可。
算一下总方案数,先考虑一个合法点对序列最多得到多少种不同的字符分配方案。这个问题相当于现有 \(\frac{n}{2}\) 个不同的元素,要将其分配至至多 \(\frac{n}{2}\) 个集合中的方案。联想到 \(\frac{n}{2}\) 个不同球放进 \(i\) 个相同盒子的数量,即第二类斯特林数,但 \(i \in [1, \frac{n}{2}]\),将枚举出来的加和即方案数,上限应该为 \(203\)。
所以总共去重前方案数上限为 \(10395 \times 203\)。
开香槟咯!统计答案:
从刚才去重过的 set 中遍历每个字符分配集合,其中每个数字对应的字符编号最大值 \(mxv\) 即这个方案的字符总种类数,答案累加上 \(A_k ^{mxv}\) 即可。
\(\color{blueviolet}{CF1559E}\)
平凡题。
先考虑前两个限制条件,背包是显著的,设 \(f_{i, j}\) 表示前 \(i\) 个数字,和为 \(j\) 的方案数,转移可以暴力枚举 \(a_i\) 取值,这个显然可以用前缀和优化到 \(O(nm)\)。
考虑枚举 \(g = \gcd(a_1, \dots, a_n)\),我们在 DP 时保证所有数字填的时候是 \(g\) 的倍数,设 \(f_{i, j}\) 表示对于当前枚举的 \(g\),处理前 \(i\) 个数字,和不超过 \(j \times g\) 的方案数。初值状态为 \(f_{0, 0} = 1\), 目标状态为 \(f_{n, m / g}\),我们发现最终并不能保证 \(\gcd\) 为 \(g\),只能保证 \(\gcd\) 为 \(g\) 的倍数,考虑容斥。设 \(ans_i\) 表示 \(\gcd\) 恰好为 \(g\) 的方案数,\(f_{n, m / g}\) 是已经求好的 \(\gcd\) 为 \(g\) 倍数的所有方案,有 \(ans_g = f_{n, m / g} - \sum\limits_{g | i\land g \not= i} ans_i\)。
所以倒序求即可,复杂度 \(O(nm\ln m)\)。
\(\color{blueviolet}{CF1583G}\)
考虑两个传送区间的关系:
- 无交集,状态互不影响。
- 相交,两者依然不会影响对方的状态。
- 包含,则大区间传送时会影响所有小区间的状态。
考虑走到一个区间 \(i\) 时(假设不存在 \(l_x < l_i \land r_x > l_i\) 的 \(x\) 这样的区间),先会将所有包含的小区间走一遍,然后传送回来,再将所有小区间再走一遍,最后走出区间。
将这个过程分为两部分(都包含传送回来这一过程):
- 走小区间再传送回来。
- 传送回来再走小区间。
这两部分的传送次数都是一样的,将其设为 \(f_i\),可以得到转移 \(f_i = 1 + \sum\limits_{l_x > l_i \land r _x < r_i} f_x\),意义上就是内部所有小区间走一遍的传送次数加上自己传送一次的总和。
这个显然可以用数据结构维护二维偏序解决。
考虑如何统计答案,如果一个区间需要被关闭,那么首先在它左侧无交集的所有区间都需要被关闭。
在左侧相交的区间也需要关闭。
然后下一过程是从区间左侧走到区间右侧再传送过程,这个过程传送贡献即 \(f_i\)。
所以对以上三种区间统计答案即可。
- 当前区间需要被关闭。
- 当前区间交在某个需要被关闭的区间左侧。
- 当前区间完全存在于某个需要被关闭的区间左侧。
二位数点即可。
\(\color{royalblue}{CF1552F}\)
首先有一个性质,所有走过的传送门都是开启状态。
设 \(f_i\) 表示蚂蚁从 \(r_i\) 传送回 \(l_i\) 再走回 \(r_i\) 需要用到的时间,这个过程中其需要走过所有 \(l_i \le r_x \le r_i\) 的传送门 \(x\)。
有转移 \(f_i = r_i - l_r +\sum \limits_{l_i \le r_x \le r_i} f_x\)。
于是我们可以考虑按照 \(r_i\) 排序,于是可以前缀和优化。
\(\color{royalblue}{CF1542D}\)
考虑对每一个元素 \(x\) 求出有多少字序列使得它产生贡献。
设 \(f_{i, j}\) 表示前 \(i\) 个操作,现在集合内有 \(j\) 个比它小的元素的总子序列数量。
首先对于 \(x_i = x_j\) 我们钦定下标更小的那一个被优先删除,这样可以避免掉重复计算。
先枚举 \(x\) 的位置 \(p\),对于 \(i < p\) 的转移:
-
第 \(i\) 个操作为删除操作,有 \(f_{i, j} = f_{i - 1, j} + f_{i - 1, j + 1} + [j = 0]f_{i - 1, j}\)。
前两项分别是选当前操作、不选当前操作的贡献,最后一项是当集合中没有比 \(x\) 小的元素时删除一个后比 \(x\) 小的元素数量为 \(0\)。
-
若 \(x_i > x\),有 \(f_{i, j} = 2f_{i - 1, j}\)。
-
若 \(x_i < x\)(因为 \(i < p\) 所以我们钦定相等也算当前情况。),有 \(f_{i, j} = f_{i - 1, j} + [j > 0]f_{i - 1, j - 1}\)。
对于 \(i = p\),有 \(f_{i, j} = f_{i - 1, j}\)。
对于 \(i > p\):
-
第 \(i\) 个操作为删除操作,有 \(f_{i, j} = f_{i - 1, j} + f_{i - 1, j + 1}\)。
-
若 \(x_i > x\)(因为 \(i > p\) 所以我们钦定相等也算当前情况。),有 \(f_{i, j} = 2f_{i - 1, j}\)。
-
若 \(x_i < x\),有 \(f_{i, j} = f_{i - 1, j} + [j > 0]f_{i - 1, j - 1}\)。
初值为 \(f_{0, 0} = 0\),统计答案即值乘以方案数即可。
\(\color{royalblue}{CF1610E}\)
我们尝试求最长的合法序列长度。
当 \(k= 1\) 或 \(k = 2\) 时都没有毒瘤序列,考虑 \(k = 3\) 时,有序序列的非法情况只有 \(c_1 < \frac{c_1+c_2+c_3}{3} < c_2 \le c_3\),这等价于 \(\frac{c_1+c_2+c_3}{3} < c_2\),即 \(c_1 + c_3 < 2c_2\)。
有结论一个毒瘤序列一定有一个长度为 \(3\) 的序列是毒瘤的,考虑反证法。
现在假设对于一个长度为 \(k\) 毒瘤序列,其中没有长度为 \(3\) 的毒瘤序列。
设 \(m = \lceil \frac{k}{2}\rceil\),对于 \(c_m\),因为序列 \(c\) 毒瘤,所以有 \(c_m\) 严格大于序列平均值。
然后考虑其中没有长度为 \(3\) 的毒瘤序列,所以对于任意 \(i\),满足序列 \(c_i, c_m, c_{k - i + 1}\) 不毒瘤,于是有 \(c_i + c_{k - i + 1} \ge 2c_m\),这个东西在 \(i = m\) 或者 \(k - i + 1 = m\) 时显然也成立。
于是有 \(\sum \limits_{i = 1}^k c_i + c_{k - i + 1} \ge 2k \times c_m\),将这个式子两侧同时除以 \(2k\) 有 \(c_m\le \frac{\sum_{i=1}^k c_i}{k}\),与之前的 \(c_m\) 严格大于序列平均值相冲突。
考虑当序列刚开始只有两个值时 \(a_x, a_y\),我们考虑从大往小加入数字,最开始加入一个数需要保证 \(a_t \le \frac{a_x + a_y}{2}\),下一次再加入一个数需要保证 \(a_t' \le \frac{a_x + a_t}{2}\),这样每次数字的选择范围会减少一半,这样至多选 \(\log\) 个。我们希望最初的的选数范围尽可能大,于是我们考虑枚举最小值 \(a_i\) 并加入 \(a_n\),然后每次加入一个能加入最大的数字,二分即可。
\(\color{royalblue}{CF1603C}\)
首先最后一个数字肯定不会被分裂,因为如果其被分裂只会使前面的数字上界减小,显然不优。
贪心地考虑分裂一个数,一定分裂成尽量均匀更优,并且让最小的数最大,举例来说将 \(9\) 分裂为不小于 \(4\) 的数时,\(3, 3, 3\) 优于 \(2, 3, 4\)。
可以知道以下性质:
- \(x\) 分裂为 \(\le v\) 的数字,最少分裂次数为 \(\lceil \frac{x}{v} \rceil - 1\),并分裂为 \(\lceil \frac{x}{v} \rceil\) 个数。
- \(x\) 分裂为 \(t\) 个数字,在最优分裂情况下其中的最小值为 \(\lfloor \frac{x}{t} \rfloor\)。
设 \(f_{i, j}\) 表示从后向前处理完第 \(i\) 个数,最小值为 \(j\) 的序列方案数,先不考虑统计答案。
对于当前的 \(a_i\),限制的上界固定,分裂出的值也固定,考虑每次拿出分裂次数相同的上界 \(l, r\),即当 \(a_i\) 需要分裂为小于 \(x \quad (l \le x \le r)\) 的数时,\(a_i\) 的分裂状态都是相同的。
设其分裂出最小值 \(v\),于是有转移 \(f_{i, v} = \sum \limits_{j = l}^r f_{i + 1, j}\)。
现在考虑统计答案,每次分裂时假设分裂为 \(t\) 个数字,则对答案有 \(i \times (t - 1) \times f_{i, v}\) 的贡献。
边界情况为 \(f_{n, a_n} = 1\)。
其中求和是单调的,可以用什么队列维护,我选择用 vector 记录,然后滚动数组优化一下即可。
\(\color{royalblue}{CF1600F}\)
一个图在点数大于等于 \(48\) 时一定有解,所以直接保留前 \(48\) 个点进行暴力判断即可,详见拉姆齐定理。
\(\color{royalblue}{CF1584E}\)
考虑最左元素最右元素状态是固定的,先只考虑左侧情况。
列出每个元素的第一次变化:
\(\begin{aligned} a_1 \leftarrow 0\\ a_2 \leftarrow a_2- a_1\\ a_3 \leftarrow a_3-( a_2- a_1)\\ a_4 \leftarrow a_4-[ a_3-( a_2- a_1)]\\ \vdots\\ a_n \leftarrow a_n-(\ldots-( a_2- a_1)\ldots) \end{aligned}\)
拆开之后有:
\(\begin{aligned} a_1 \leftarrow 0\\ a_2 \leftarrow a_2- a_1\\ a_3 \leftarrow a_3- a_2+ a_1\\ a_4 \leftarrow a_4- a_3+ a_2- a_1\\ \vdots\\ a_n \leftarrow \begin{cases} a_n- a_{n-1}+\cdots+ a_1 n\equiv1\pmod 2\\ a_n- a_{n-1}+\cdots-a_1 n\equiv 0\pmod 2 \end{cases} \end{aligned}\)
发现是正负交替和,所以有以下限制:
- 整个序列正负交替和等于 \(0\)。
- 每个前缀正负交替和非负。
考虑枚举右端点,维护有多少左端点合法。
因为奇偶正负项不同,可以分开维护。
对于第二个限制,只要每次加入新元素后弹出不合法值即可,第一个只需要找到加入 \(a_r\) 为 \(0\) 的交替和即可,加入 \(a_r\) 即根据奇偶性在两堆数字中都加减 \(a_r\) 即可。
于是需要维护操作:
- 所有数字加一个数。
- 插入一个数。
- 查找等于某数的个数。
- 删除所有大于 \(0\) 或小于 \(0\) 的数。
显然的 map 即可。
\(\color{blueviolet}{CF1616F}\)
转换一下限制,对于一个三元环的三条边 \(a, b, c\) 有 \(col_a + col_b + col_c = 0 (\mathrm{mod}\ 3)\),于是我们得到了一堆模 \(3\) 意义下的方程,高斯消元即可。
\(2024.1.15-2024.1.28\)
咕咕咕了。