做题记录
做题记录
CF10C Digital Root
容易发现当 \(x=9k\) 时 \(d(x)=9\),否则 \(d(x)=x\bmod 9\)。
可以考虑枚举 \(A\) 和 \(B\) 所对应的 \(d\),计算出所对应的 \(d(C)\),分别计数 \(d(A)\),\(d(B)\),\(d(C)\) 在 \(1-n\) 内有多少个,根据乘法原理乘起来即可。
对于 \(AB=C\) 的情况,可以算完之后再减。由于 \(d(A)\times d(B)=AB\bmod 9=d(C)\),要减去的显然为 \(\sum_{i=1}^n[\frac{n}{i}]\)。数据范围很小所以可以不用整除分块。
CF13B Letter A
枚举端点判断是否存在有相同端点线段。
求出每条线段的解析式 \(kx+b=y\),可以求出第三条线段与前两条线段的交点坐标,判断交点坐标是否在线段内即可。
可以利用两点间距离公式 \(\sqrt {(x_1-x_2)^2+(y_1-y_2)^2}\) 求出第三条线段所分割的两条线段长度,按照题目要求判断。
对于角度的问题,在上一次判断中已经求出了所有线段长度,由于它们构成了一个三边长度已知的三角形,不难想到利用余弦定理 \(\cos a=\frac{B^2+C^2-A^2}{2BC}\)计算角度判断即可。
有一些细节需要注意,比如与 \(y\) 轴平行的线段的斜率处理方式、精度是否会炸。
CF15C Industrial Nim
根据题目名称和题面不难发现这是一道 \(nim\) 游戏的题目。
根据 \(nim\) 游戏的结论,若所有车容量的异或和为 \(0\) 则后手胜,否则都是先手胜。(先手必然可以找到一种方法使当前局面状态在操作后异或和为 \(0\),一直持续到 \((0,0,\dots,0)\) 的状态,后手无法保持异或和为 \(0\))
一个暴力的做法是,我们直接计算所有车容量的异或和 \(\operatorname{xor}_{i=1}^n\operatorname{xor}_{j=x_i}^{x_i+m_i-1}j\),但是显然会 T。考虑如何优化 \(\operatorname{xor}_{j=x_i}^{x_i+m_i-1}j\) 这一部分,这其实就是一个连续自然数段的异或和问题,可以转换成如何在 \(O(1)\) 复杂度内求解 \(\operatorname{xor}_{i=1}^{n}i\)。
P3908 是模板。考虑到对于一个奇数 \(k\),\((k-1) \operatorname{xor} k\) 一定等于 \(1\),所以我们可以把 \(1-n\) 分成很多个这样的“奇数对”,异或之后就是一堆 \(1\)。所以可以发现答案与 \(n\bmod 4\) 的值有关。结论是这样的:
\(n\bmod 4=0: \operatorname{xor}_{i=1}^{n}i=n\)
\(n\bmod 4=1: \operatorname{xor}_{i=1}^{n}i=1\)
\(n\bmod 4=2: \operatorname{xor}_{i=1}^{n}i=n+1\)
\(n\bmod 4=3: \operatorname{xor}_{i=1}^{n}i=0\)
这样就可以实现 \(O(1)\) 求解连续自然段异或和了。对于本题,扫一遍 \(1-n\),对于每一个区间按照结论求异或和即可。
CF18D Seller Bob
不难想到一个 \(dp\):设 \(f_i\) 代表现在已经考虑到了前 \(i\) 天,目前能够得到的最大收益。当第 \(i\) 天为 win 时,显然可以直接从前一天转移:\(f_i=f_{i-1}\);否则第 \(i\) 天为 sell,可以选择卖或不卖两种状态,不卖的状态为 \(f_{i-1}\),卖的状态为 \(f_{lst_{x_i}}+2^{x_i}\)(其中 \(lst_{x_i}\) 代表 \(x_i\) 型号的硬盘上一次是第几天出现的)直接取 \(\max\) 即可。
可以同时在 \(O(n)\) 复杂度内转移,同时注意本题答案可能达到 \(2^{2000}\),所以需要 \(O(|w|)\) 的复杂度维护高精度,总时间复杂度 \(O(n|w|)\)。
CF21C Stripe 2
重题 CF466C。
我的唐氏做法是,维护两个数组分别维护所有前缀和、后缀和等于 \(\frac{\sum a_i}{3}\) 的下标。枚举第一个数组中的下标,用二分找出第二个数组中所有在该下标后面的下标,相当于这两个下标对应了从哪分成三段。直接统计答案即可。复杂度带 \(log\),其实本来可以线性的。
CF29D Ant on the Tree
数据范围弱到了 \(n\le 300\),但由于本人写树上差分写魔怔了所以写了个 \(O(nlogn)\) 的做法。只需要每次对两个叶子结点所经过的边做边差分,最后统计每条边经过次数即可。最后输出路径随便拿记录的父亲搞搞都能过。
CF920F SUM and REPLACE
势能线段树板子题。根据唯一分解定理,\(d(n)=(a_1+1)\times (a_2+1)\times \dots (a_k+1)\),其中 \(a_i\) 代表 \(n\) 的第 \(i\) 个质因子的次数。显然对于 \(10^6\) 的数量级,用不了几次取因数个数和操作就会变成 \(1\) 或 \(2\),然后再也不会改变。
上势能线段树即可,暴力修改叶子,复杂度可过。
CF1325D Ehab the Xorcist
挺神仙的一道题。
一个结论是,合法的 \(u\) 一定小于等于 \(v\),因为在没有进位的二进制运算中,异或等价于加法。
于是我们考虑把多的那部分 \(v-u\) 拆开变成相同的几部分,这样不改变和 \(v\),同时保证了这几部分在异或中没了,只剩下 \(u\)。容易发现 \(u,\frac{v-u}{2},\frac{v-u}{2}\) 是一种不错的构造(\(u\) 与 \(v\) 的奇偶性是相同的,所以这种构造是对的)。
还可以再优化吗?根据样例我们发现还是可以在某些特殊情况下优化到 \(2\) 个元素的。我们可以考虑提前将 \(u\) 和 \(\frac{v-u}{2}\) 异或了,这样异或和没有影响,同时当 \(u\) 和 \(\frac{v-u}{2}\) 二进制没有相同的 \(1\) 时,加法不会发生进位。根据刚刚的结论,此时异或等价于加法,即总和也没有影响。
总结一下:当 \(u\& v=0\) 时,有更优的构造:\(u\operatorname{xor}\frac{v-u}{2},\frac{v-u}{2}\),否则按照刚刚的三个元素方法构造即可。
CF1572B Xor of 3
绝妙构造,我总是想不出来。
这道题的突破口在于,什么时候有解。我们发现当且仅当这三个数中有一个 \(1\) 两个 \(0\),或者一个 \(0\) 两个 \(1\) 时,修改才有效。
此时每次修改会减少或增加两个 \(1\),所以可以推出最后我们一定会修改偶数个 \(1\)。所以有解的其中一个条件是总共有偶数个 \(1\),或者异或和为 \(0\)(换一种说法)。
接下来我们可以分讨 \(n\) 的奇偶。
当 \(n=2p+1\) 时:对 \(n-2,n-4,\dots,1,1,\dots,n-4,n-2\) 分别进行修改(这里每个数代表修改的左端点,即 \([l,l+2]\) 中的 \(l\))。
当 \(n=2p\) 时:找出一个 \(1\le k\le n\),满足 \(k=2q+1\) 且 \(a_1,a_2,\dots,a_k\) 中有偶数个 \(1\),即前缀异或和为 \(0\),按照上面的方法分别处理 \([1,k]\) 和 \([k+1,n]\) 即可。若找不出 \(k\) 则说明无解。
正确性证明:
当 \(n=2p+1\) 时:可以发现经过前 \(\frac{n-3}{2}+1\) 次操作 \(n-2,n-4,\dots,1\) 后,\(a_1\) 的值等于序列的异或和,根据上面有解的分析,可知此时 \(a_1=0\),并且满足 \(a_{2p}=a_{2p+1}\),因为它们在同一组中被修改。此时我们再做后 \(\frac{n-3}{2}+1\) 次操作 \(1,\dots,n-2,n-4\),每个 \(a_1,a_3,a_5,\dots,a_{n-2}\) 都会带着其后面的两个相同的数 \(a_{2p},a_{2p+1}\) 一块变成 \(0\)。由于在前 \(\frac{n-3}{2}+1\) 次操作中 \(a_1=0\),所以后面一定都会变成 \(0\)。总操作次数 \(2\times(\frac{n-3}{2}+1)=n-1\),满足要求。
当 \(n=2p\) 时:有了上面的证明,这种情况的证明显然。这里证明一下关于为什么找不出一个前缀异或和为 \(0\) 的奇数项 \(k\) 则可以直接判断无解。此时序列只可能为开头、结尾是 \(1\),中间是很多个长为 \(2\) 的 \(01\) 块的形式。我们想把开头的 \(1\) 消去,发现需要对第三位取反,这需要通过第五位取反实现……由于 \(n\) 是偶数,开头和结尾的 \(1\) 肯定不能同时消掉。
CF468C Hack it!
神仙。
我们令 \(q=\sum_{i=0}^{10^{18}-1}f(i) \bmod a\)。
注意到
同理可推出 \(\sum_{i=2}^{10^{18}+1}f(i) \bmod a=q+2\),\(\sum_{i=3}^{10^{18}+2}f(i) \bmod a=q+3\dots\)
我们得出结论:\(\sum_{i=p}^{10^{18}+p-1}f(i) \bmod a=(q+p)\bmod a\).
容易发现令 \(p=a-q\) 是一种合法的构造。现在的问题是如何求出 \(q\)。
我们拆位考虑,每位的贡献为 \(x\times 10^{17}(0\le x\le 9)\),最后乘以 \(18\) 即可。
P7119 Mivik 的游戏
注意到如果我们想要把一个反面硬币变成正面,令当前位置为 \(a\),目前总共有 \(k\) 个反面硬币,则硬币的翻面会按照 \(k,k+1,\dots,a,a-1,a-2,\dots,k\) 进行,一轮总共会翻 \(2a-2(k-1)\) 次。
关键就在于对于每个反面硬币,翻面时都是按照先从当前 \(k\) 开始,往前再往回,直到一圈回来,该硬币变成正面。然后 \(k=k-1\),继续翻下一个硬币。
这样就不难发现对于一个状态,我们可以写出其操作次数:
推一下就等于 \(2\sum a_i-k^2\) 了。
也就是说,我们需要在每次区间取反后,迅速求所有反面硬币的下标之和,还有反面硬币的个数。显然可以使用线段树解决。
P11140 [APC001] E - Linear Map
好题啊!朴素的 dp 不难想出:令 \(f_i\) 代表只考虑前 \(i\) 位的答案,则 \(f_i=\sum f_j\),其中 \(1\le j\le i-1\) 且 \([j+1,i]\) 合法。但这样的复杂度显然是过不了的。
优化 1:经过手模或一些证明,可以发现合法的串长度不超过 \(9\)。这直接大大减少了我们的复杂度!但是遗憾的是 \(O(81n)\) 的复杂度仍无法通过本题。
优化 2:接下来要观察到合法串的长度是单调的,即若 \([l,r]\) 合法,那么 \([l+1,r]\) 也一定合法。我们利用双指针求出 \(i\) 往左能拓展到的最远的点,使得形成的区间合法。利用这个我们就可以在 \(O(n)\) 的复杂度内完成 dp。
P6328 我是仙人掌
记得很久之前见过这道题(当时好像是紫?)被 lxl 和 Ynoi 吓跑了。
由于 \(n\) 只有 \(1000\) 而且无边权,我们可以先 \(O(n^2)\) 预处理出任意两点间的最短路。
接下来考虑 dp 转移。令 \(f_{i,j}\) 代表 \(i\) 到所有最短路小于等于 \(j\) 的点的集合。我们可以使用 bitset 大法压位。先标记所有 \(f_{i,dis_i}\) 的第 \(i\) 位,然后朴素转移即可:\(f_{i,j}|=f_{i,j-1}\)。这部分的复杂度是 \(O(\frac{n^3}{W})\) 的,能够卡过。
再考虑如何求答案,不难发现答案实际上就是所有 \(f_{x_i,y_i}\) 的按位或再求 \(1\) 的个数。复杂度 \(O(\frac{\sum a\times n}{W})\),同样可以卡过。
这里有一个很奇怪的地方,我使用链式前向星竟然诡异的 T 了,但是改成邻接表就 500ms 过了?
不知道是否正确的解释:趋于完全图时,使用邻接表会更快。
CF555E Case of Computer Network
唯一有趣的一个 trick 就是 E-BCC 可以通过边定向转换成 SCC。
所以如果 \(s\) 和 \(t\) 在一个 E-BCC 里,那么我们不需要考虑,因为肯定有一种定向方案成立。于是我们考虑边双缩点,这样就形成了一棵树,我们只需要关心树上两点的 \(s,t\),可以将 \(s-lca\) 这一段加上一个“往上方向”的 tag,将 \(lca-t\) 方向加上一个“往下方向”的 tag,这样这条路径就已经被定向了。
可以使用树上差分维护路径修改操作,最后判断一条边是否只有“往上方向”或“往下方向” tag 中的其中一种。特别注意图可能不连通。
CF2021C2 Adjust The Presentation (Hard Version)
Easy Version 中的性质比较显然,\(b\) 中任意两数的相对位置关系和 \(a\) 应该是一样的,因为只能从头取。
所以我们令 \(p_i\) 代表 \(a_i\) 第一次在 \(b\) 中出现的位置,如果没有出现则设为 \(inf\),不难发现当 \(p\) 不下降时是合法的。这个可以 \(O(n)\) 判。
对于修改操作,其实只会影响原本 \(b_x\) 所对应的那个 \(p_i\) 和 \(y\) 所对应的那个 \(p_i\),考虑用 set 维护所有 \(b_i\) 的位置。此时问题转换成了单点修改,全局查是否不下降,使用线段树维护最小值和最大值即可。
CF979D Kuro and GCD and XOR and SUM
询问中要满足的条件看起来太苛刻了,我们考虑简化一些条件。
首先第一个条件实际上就是固定了上界,\(v\le s-x\),第二个条件不难发现这里的 \(\gcd\) 并没有什么用,我们转换成 \(k|v,k|x\)。所以我们就可以在 \(x\bmod k\ne 0\) 或 \(s-x<k\) 时判无解。
接下来的问题就转换成了固定上界,在集合中选一个 \(k\) 的倍数,并最大化 \(v\oplus x\) 的值。
看到类似按 \(k\) 的倍数,模 \(k\) 分类一类的字眼,应该想到根号分治。我们分讨 \(k\) 的大小,令 \(W=10^5\) 为值域,若 \(k>\sqrt w\),注意到值域内 \(k\) 的倍数数量小于 \(\sqrt W\),直接枚举即可;若 \(k\le \sqrt w\),我们考虑预处理所有这样的 \(k\) 的答案,具体来说,我们开 \(\sqrt W\) 棵 01-Trie,把集合中该数的倍数全插进去,查询时相当于转换成了“一个序列,每次给你一个数,从序列中选一个数使两数异或起来最大”,在 Trie 上查询即可。
CF1093G Multidimensional Queries
这个题很好的启示了我们结合曼哈顿距离和拆位的关系。
如何想到拆位?曼哈顿距离中难处理的点在于绝对值,由于我们无法处理大小关系,导致绝对值很难被拆掉。注意到 \(k\le 5\),那么我们能否用一个二进制状态,表示“如何拆绝对值”,具体来说对于第 \(i\) 位,若 \(x_i-y_i>0\),我们把状态的该位设成 \(1\),否则设成 \(0\)。
但这样是没有普遍性的,我们考虑把二进制状态映射到每个点上。我们令 \(f(a,i)=\sum_{j=1}^k-1^{a_j}\times x_j\),其中 \(i\) 代表一个点,\(a\) 代表一个状态,不难发现 \(dis(i,j)=\max_{a=0}^{2^k-1}f(a,i)-f(a,j)\),即在不同二进制下的 \(f\) 相减得到的最大值(为什么是最大值?因为你此时把任何一个地方交换位置就会出现负数)。
我们把减法替换成加法,即 \(dis(i,j)=\max_{a=0}^{2^k-1}f(a,i)+f(b,j)\),其中 \(b\) 是 \(a\) 的补集。
最后求答案就显然易见了,我们的线段树维护 \(2^k\) 个 tag,分别存储每一个状态 \(a\) 的区间最值,即 \(\max_{i=l}^rf(a,i)\),求答案时只需要枚举每个状态并计算出其和其补集的区间最值加起来取 \(\max\) 即可。注意本题略卡常,不要开 \(2^k\) 棵线段树。
P2633 Count on a tree
借这题学一学主席树。
主席树实际上是值域上的可持久化线段树,主旨在于优化掉对于每个历史版本都要开一棵线段树的冗余空间。
我们考虑该题的弱弱弱化 Version,即“链上查全局第 \(k\) 小“,不难发现可以用动态开点值域线段树上二分解决。
我们考虑该题的弱弱化 Version,即“链上查 \([1,r]\) 第 \(k\) 小“,不难发现可以把每个 \(1\le r\le n\) 看成一个“历史版本”,分别建 \(n\) 棵线段树,之后找到询问的那个版本并结合上一 Version 即可。但这样时空复杂度都是不对的,我们考虑两棵相邻的线段树其实只在一条链上有差异(对 \([1,n]-[val_r,val_r]\) 这条链),而线段树从根开始的一条链的长度是 \(log\) 的,我们考虑只修改这些点,结合动态开点(每个新版本只新开 \(log\) 个点)这样复杂度就降为了 \(O(nlogn)\),可以解决,这也是主席树的朴素思想。
我们考虑该题的弱化 Version ,即“链上查 \([l,r]\) 第 \(k\) 小“,不难发现由于每个版本的线段树形态相同,我们拿第 \(r\) 个版本和第 \(l-1\) 个版本做类似“前缀和、差分”的操作,两棵线段树权值相减即可。结合上一 Version 的主席树可以解决。
我们考虑该题,即 “树上查路径第 \(k\) 小”,不难发现我们可以同样选择类似“前缀和、差分”的操作,可以使用树上差分,将第 \(u\) 个版本加上第 \(v\) 个版本,再减去第 \(lca(u,v)\) 个版本和第 \(father_{lca(u,v)}\) 个版本即可,结合主席树可以解决。
ABC380G Another Shuffle Window
枚举 \(1\le i\le n-k+1\) 是必要的,问题在于如何处理逆序对个数的期望。不难发现我们可以将排列分成三段,即 \([1,i),[i,i+k),[i,k,n]\)。
第一段和第三段的逆序对个数是固定的,相当于前缀逆序对和后缀逆序对,使用权值树状数组或线段树正反扫一遍即可,第二段的逆序对个数是个期望,由于排列内数互不相同,可以转换成“长为 \(n\) 的排列任意重排,期望逆序对个数”这个经典问题,可以证明答案是 \(\frac{n(n-1)}{4}\)。
注意到还剩下两的逆序对没有处理,即左端点在 \([1,k)\),右端点在 \([k,n)\) 和左端点在 \([1,i+k)\),右端点在 \([i+k,n]\) 的逆序对个数,这个同样是好求的,使用主席树即可。
P5283 [十二省联考 2019] 异或粽子
区间 \(\operatorname{xor}\) 是不太好做的,我们转换成前缀异或和,相当于总共要选 \(k\) 个数对 \((l,r)\) 满足 \(1\le l\le r\le n\),每个对的贡献为 \(sum_r \oplus sum_{l-1}\),最大化贡献总和。
又注意到限制 \(l\le r\) 是不太好做的,因为我们无法随便选,一个比较经典的 trick 是将其转换为随便选的情况,此时需要将 \(k\) 乘以 \(2\)(贡献会算两遍),那么相当于总共要选 \(2k\) 个数对 \([l,r]\) 满足 \(1\le l,r\le n\),其余同上。由于 \(l=r\) 时贡献为 \(0\),而题目中要求最大化贡献和,所以不用担心正确性。
比较好证明我们要选所有最大的贡献,那么一个比较经典的解决方法就是使用优先队列,对于每一个 \(i\),我们先求出 \(\max(sum_i \oplus sum_j)\) 并扔进优先队列里,每次取出的队首都计入答案,并将其次大贡献丢进去。同理如果取出了次大,就计入答案后再丢进第三大值,以此类推。这个做法的正确性也是比较好证明的。
现在就只需要处理 \(\operatorname{maxt}(sum_i \oplus sum_j)\) 了,其中 \(\operatorname{maxt}\) 代表第 \(t\) 大的结果。这又是一个经典问题,可以想到把每个 \(sum\) 插入 01-Trie 里,在 Trie 上求第 \(t\) 大即可,原理基于贪心。
ARC187B Sum of CC
连这个都不会了。人生已经失败完了。
注意到连通块一定是一个区间。证明就是考虑 \(1\le l\le r\le n\) 且满足 \(a_l\le a_r\),那么对于区间中任意一个数,要么小于等于 \(a_r\) 和 \(r\) 连边,要么就大于等于 \(a_l\) 和 \(l\) 连边。那么我们只需要维护那些连通块中间的断点,答案就是断点个数加一。
一个点什么时候成为断点?当且仅当你左边的前缀 \(\min\) 大于你右边的后缀 \(\max\),结合上面的性质这个是很好证明的。不妨令 \(f_{i,j},g_{i,j}\) 分别表示第 \(i\) 个数,左/右边最小/大值大于/小于等于 \(j\) 的方案数,发现可以直接使用快速幂计算结果。答案的贡献就是所有的 \(f_{i,j}\times (g_{i,j-1}-g_{i,j-2})\) 之和(枚举右边的后缀 \(\max\) 的确切值 \(j\)),可以在 \(O(nm\log (n))\) 的复杂度内完成计算。
CF1270G Subset with Zero Sum
神仙。
\(i-n\le a_i\le i-1\) 看起来不太好处理,但注意到式子左右两边都有一个 \(i\),所以可以移向得到 \(1\le i-a_i\le n\)。这有什么用?注意到题目中保证一定有解,而且 \(i-a_i\) 一定在合法范围内,并且满足迭代性质。我们发扬人类智慧,考虑建图。
对于所有 \(i\),将 \(i\) 向 \(i-a_i\) 连一条有向边,这样就形成了一棵基环树(根据上面式子易证),此时环上的所有点所形成的集合就是答案。
为什么这样是对的?此时说明 \(i-a_i-a_{i-a_i}-a_{i-a_i-a_{i-a_i}}-\dots =i\),而如果我们移项则会发现等式变成了 \(0\),这也正是上面说的对其“迭代性质”的应用。
AGC002E Candy Piles
是一个很厉害的组合意义博弈论题。
我们将 \(a_i\) 从大到小排序,这样第一种操作就转换为了从左边拿走一堆,第二种操作就转换为了从下面拿走一行。我们不妨用网格图理解这件事,构建一个 \(\max(a_i)\) 行 \(n\) 列的网格,其中第 \(i\) 列有一条长为 \(a_i\) 的垂直线段。假想初始状态在 \((1,1)\),第一种操作相当于往右移一格,第二种操作相当于往上移一格。当这步移到边界时,该玩家就寄了,这样我们将其转换为了一个更直观的博弈游戏。
接下来我们考虑那些状态可以归为同一类,即拥有相同的必败或必胜态。不难发现 \((i,j)\) 和 \((i+1,j+1)\) 的状态应该是相同的(若 \((i,j)\) 必胜,则 \((i+1,j),(i,j+1)\) 至少有一必败,则 \((i+1,j+1)\) 必胜,反之亦然)于是我们只需要求出网格图中最大的在边界内的 \((i,i)\),接下来对面只能一直往上或一直往右或不动,根据奇偶性分讨即可。
CF1789F Serval and Brain Power
第一眼看上去 \(n\le 80\),启发我们乱搞,但并没有什么可做的方法,同时注意到题目中并没有给你 \(k\),需要你枚举,这启发我们对 \(k\) 乱搞,即对 \(k\) 的大小进行“分治”。
先解决 \(k=2,3\) 的情况,此时我们可以将序列分成 \(2,3\) 段,并对这些段做多模 LCS 匹配,复杂度为 \(O(n^{2k-1})\),最高达到了 \(O(n^5)\),但注意到常数极小,加上最优性剪枝完全可以通过。注意到 \(k=4\) 时实际上被 \(k=2\) 的情况包括了,所以不用考虑。
接下来考虑 \(k\ge 5\) 的情况,一个很显然的性质是周期长度不超过 \(\frac{n}{k}\),那么最长取 \(\frac{80}{5}=16\),发现可以枚举周期起点并枚举这 \(16\) 位选或不选,复杂度 \(O(2^{16}n)\),我们还需要再扫一遍序列,判断这个周期是否出现了至少两次,所以这部分总复杂度 \(O(2^{16}n^2)\),同样可以通过。
CF1768F Wonderful Jump
神仙。
\(O(n^2)\) 的 dp 不难想到,尽管这个东西看起来是很显然的 dp 优化,但是由于没有决策单调性,斜率、数据结构等都无法优化。
考虑挖掘性质。一个性质是我们发现一次跳跃的两端点必有其中一个是整个区间的最小值,即若从 \(i\) 跳到 \(j\),必有 \(a_i=\min_{k=i}^ja_k\) 或 \(a_j=\min_{k=i}^ja_k\)。证明可以考虑反证,若存在 \(i\le k\le j\) 并满足 \(a_k=\min_{k=i}^ja_k\),那么如果先从 \(i\) 跳到 \(k\) 再从 \(k\) 跳到 \(j\) 的代价为 \(a_k\times ((k-i)^2+(j-k)^2)\),一定是比直接从 \(i\) 跳到 \(j\) 的代价 \(a_k\times (j-i)^2\) 更优的,矛盾。
另一个性质是若当前一次跳跃的一个端点是 \(i\)(\(a_i\) 是最小值),那么这次跳跃的距离不应该超过 \(\frac{n}{a_i}\)。如何证明?突破口在 \(a_i\le n\)。如果我们一步步的跳,代价是不超过 \(dn\) 的,其中 \(d\) 代表总步数,如果直接跳 \(d\) 的距离,代价则是 \(a_id^2\) 级别的。也就是说我们选择一次跳 \(d\) 步当且仅当 \(a_id^2\le dn\),解得 \(d\le \frac{n}{a_i}\),得证。
利用上面两个性质,我们就可以从另一个角度来优化这个 dp 了,考虑根号分治。
我们枚举每一个 \(i\) 作为跳跃端点的最小值,则我们对 \(a_i\) 的大小进行根号分治。若 \(a_i>\sqrt n\),说明最优的跳跃距离不会超过 \(\sqrt n\),暴力枚举即可;否则我们将所有相同的 \(a_i\) 分成一组,并同样考虑暴力,由于小于 \(\sqrt n\) 的 \(a_i\) 去重后此时只有 \(\sqrt n\) 个,所以总复杂度是 \(O(n\sqrt n)\) 的,可以通过。
P8867 [NOIP2022] 建造军营
一个很直观的想法是通过 E-BCC 缩点转化为一棵树。
我们令缩点后每个 E-BCC 中点数为 \(v_i\),边数为 \(e_i\),那么由于每个分量内部可以随便选择建不建军营、看不看道路,所以内部建军营的方案是 \(2^{e_i}\),不建的方案是 \(2^{e_iv_i}-2^{e_i}\)。接下来要考虑分量之间,不难发现这个东西具有转移性质,考虑树形 dp。
令 \(f_{u,0/1}\) 表示 \(u\) 子树中选/不选军营的方案数,满足若选军营则必须都与 \(u\) 连通,并且 \(u-fa_u\) 这条边不能看守。(不连通则状态不够专移,父边看守则具有后效性)
转移如下,\(f_{u,0}=\prod_{v\in son_u} f_{v,0}\times 2\),\(f_{u,1}=f_{u,1}\times (f_{v,0}\times 2+f_{v,1})+f_{u,0}\times f_{v,1}\)。
答案分根和普通节点分类讨论即可。为了避免选择父边,需要 \(2^{total-sz_u-1}\) 而不是 \(2^{total-sz_u}\),这里 \(total\) 代表树边数,\(sz_u\) 代表子树内边数。
CF2031E Penchick and Chloe's Trees
不会做。遗憾离场。
这类题应该只能树形 dp。令 \(f_u\) 表示 \(u\) 子树内操作能使子树同构的最小深度,这里子树内以 \(u\) 为最低深度。\(u\) 为叶子时显然 \(f_u=1\),\(u\) 只有一个儿子时深度就加一,即 \(f_u=f_v+1\),考虑如何处理多个儿子的情况。
转换为一个更一般的问题,对所有 \(f_v\) 建一个 multiset,每次取出所有的 \(\min\) 值,并重新插入 \(\frac{cnt+1}{2}\) 上取整个 \(\min+1\),最后只剩一个时那个数就是答案。
这个很好理解,相当于把 \(v\) 的那些小满二叉树依次尝试深度,看能不能构成一个大的满二叉树。
但这样的复杂度是 \(O(n^2logn)\) 的,即使避免掉 DS 的 \(log\) 也无法通过。我们发现这样做的瓶颈在于每次只加一,我们考虑压缩跳的深度。
具体来说,令二元组 \((x,y)\) 代表有 \(y\) 个 \(y\),预处理出将 \(x_i\) 变成 \(x_{i+1}\) 的新 \(y\) 值,其中 \(x\) 有序。相当于我们一个二元组只会跳到和下一个相同的深度,然后再一起跳。这样就避免掉了一个 \(O(n)\),总复杂度 \(O(nlogn)\),据说还有 \(O(n)\) 的神仙做法。
P6280 Exercise G
这类排列上跳的问题,平凡地考虑建图后求环长 \(\operatorname{lcm}\)。
问题转换成所有可能构造出的环长 \(\operatorname{lcm}\) 之和。由于值域很小,不难想到质因数分解后拿质因数 dp,令 \(f_{i,j}\) 代表只用了前 \(i\) 个质数,环长和为 \(j\) 时对答案的贡献,转移显然。
然后这个东西很好滚动数组优化到一维。
彩蛋:P4161 同理。
P3232 [HNOI2013] 游走
把对边的限制放到点上,求出点的期望经过次数,然后贪心赋权即可。
于是高消解图上期望 dp。
P7105 「C.E.L.U-01」门禁
令 \(f_s\) 表示 \(s\) 内部连通的概率(\(s\) 是一个二进制数),转移结合枚举子集是朴素的。
复杂度 \(O(3^n\times n^2)\),可以卡过。
[ABC136E] Max GCD
考虑什么是不变的。由于值域很小,对 \(10^6\) 入手,不难发现答案一定是 \(\sum_{i=1}^n a_i\) 的因数,而枚举这个和的因子是 \(\sqrt{10^9}\) 量级的。
现在我们来考虑一个 check。对于因子 \(m\),我们将序列所有数模上 \(m\),贪心的选择肯定是余数小的减,余数大的加,随便 \(O(n\log n)\) 排序后双指针扫一下即可求出最小操作次数,和 \(k\) 比一下即可。
[AGC052B] Tree Edges XOR
神题。我们考虑将边权转为点权,考虑构造一种更简单的操作。我们令 \(\operatorname{val}_u\) 代表根到 \(u\) 路径上边权的异或之和.
CF600E
考虑线段树合并。每个点维护一棵线段树(下标为颜色,区间维护最多次数和答案),跑一遍 dfs,将自己和儿子进行线段树合并即可。
CF2078E
好久没补做题计划了。
最多问 \(2\) 次,那肯定是拆成两段分别问,仔细想下问 \(0\) 可以求出 \(x+y\) 但没啥用。
我们发现最后不太需要求出 \(x,y\) 的确切值,也不能求出。我们不妨这样问:\(101010101\) 和 \(010101010\)。
为啥是对的呢?分析一下,当 \(n\) 的第 \(i\) 位是 \(1\) 时,贡献为 \(2^{i+1}\),否则若 \(x_i=1,y_i=1\) 贡献为 \(2^{i+1}\),若 \(x_i,y_i\) 有一个为 \(1\) 贡献为 \(2^{i}\),否则为 \(0\)。我们得到结果后减去一定会贡献的那个 \(2n\),发现剩下的只有奇数/偶数位的贡献,而因为每个位最多占两个,所以不会出现进位重叠的情况。
P5369 [PKUSC2018] 最大前缀和
期望乘上 \(n!\) 等价于没有期望。
所以求的其实是每个最大前缀和的排列方案数,注意到 \(n\le 20\),所以不同的最大前缀和至多有 \(2^{20}\) 种,考虑状压 dp。
考虑一个前缀 \(p_1,p_2,\dots,p_i\) 什么时候成为最大前缀和,当且仅当 \(\forall j<i,\sum\limits_{k=j}^{i}p_k\ge 0\) 以及 \(\forall j>i,\sum\limits_{k=i+1}^{j}p_k\le0\),既不存在「削去一段使答案更优」的情况。
发现这两个约束是独立的,一段是 \([1,i]\),一段是 \([i+1,n]\),分别令 \(f_{state},g_{state}\) 代表满足「最大前缀和的 \(p_1,p_2,\dots,p_i\) 为集合 \(state\)」的约束 \(1,2\) 的方案数。答案就是 \(\sum\limits_{state} (\sum\limits_{i\in state}p_i)\times f_{state}\times g_{2^n-1-state}\)。
转移就是考虑新填一个数是否合法,既 \(f_{i|state} \leftarrow f_{state}\times [sum\ge 0],g_{i|state} \leftarrow g_{state}\times [sum+p_i<0]\)。复杂度 \(O(2^n\times n)\)。
P4458 [BJOI2018] 链上二次求和
先考虑静态的情况,然后推一下式子,发现需要维护:\(s_i=\sum\limits_{j=1}^ia_j,s'_i=\sum\limits_{j=1}^is_j,s''_i=\sum\limits_{j=1}^is'_j,s'''_i=\sum\limits_{j=1}^is_j\times j\)。
每次修改重新维护这些东西是 \(O(nq)\) 的,然后再推一下式子,发现需要维护差分数组 \(b\) 的 \(\sum b_i,\sum b_i\times i,\sum b_i\times i^2,\sum b_i\times i^3\)。
然后再推一下式子,树状数组维护即可。总之就是恶心题,复杂度 \(O(q\times \log n)\)。
P8600 [蓝桥杯 2013 省 B] 连号区间数
一个区间连续,等价于 \(\max-\min=r-l\)。
一个区间的 \(\max-\min\ge r-l\)。
扫描线,维护 \(\max-\min\) 的最小值及其数量。更新 \(\max,\min\) 的时候可以用两个单调栈。
P6190 [NOI Online #1 入门组] 魔法
很有趣的题目,考察对邻接矩阵、 \(\min+\) 矩阵 的进一步理解。
部分分给了 \(k=0\),启示我们应该从小到大考虑 \(k\) 的做法。
\(k=0\) 时是显然的,直接跑一遍最短路。
\(k=1\) 时貌似是个 dp,数据范围启示我们考虑 \(O(n^3)\) 的 floyd 类状物。我们令 \(f_{i,j,k}\) 代表从 \(i\) 到 \(j\),至多用 \(k\) 次魔法的最小答案。\(f_{i,j,0}\) 就是直接 floyd,\(f_{i,j,1}\) 可以考虑钦定一条魔法边 \((u,v,w)\),然后转移就是 \(f_{i,j,1}\leftarrow f_{i,u,0}+f_{v,j,0}-w\)。
目前这部分复杂度 \(O(n^3+mn^2)\)。
对于 \(k\) 更大的情况,我们同样考虑类似 floyd 的转移方式,既枚举中转点 \(x\),则可以转移 \(f_{i,j,k}\leftarrow f_{i,x,k-1}+f_{x,j,1}\)。
仔细观察这个式子,其实就是那个邻接矩阵的一次 \(\min +\) 自乘。所以我们定义单位矩阵为 \(f_{i,j,0}\),然后求 \(f_{i,j,1}\) 的 \(k\) 次方就行,答案是 \(f_{1,n,k}\)。复杂度 \(O(n^3\times \log k)\)。
5.25 NOI 联考 T1 基环
直接考虑连基环比较困难,我们先考虑当图中已有环的时候怎么做。不难发现如果我们把原图的若干连通块缩起来,那么问题转换成生成树的带权计数,其中对于连通块 \(i,j\),令其大小为 \(cnt_i,cnt_j\),则连这条边的贡献是 \(cnt_i\times cnt_j\)。 根据 Cayley 定理的扩展形式,\(tot\) 个连通块的有标号生成树数量为 \((\sum\limits_{i=1}^{tot} cnt_i)^{tot-2}\times \prod\limits_{i=1}^ncnt_i\)。于是我们先特判掉这种情况。
接着考虑原问题,我们可以先对基环计数,找出基环后将其当成一个「已有」的连通块,再继续做上面的那种情况。我们考虑如何计数基环,发现基环是由若干个连通块构成的。我们这里对连通块的个数 \(k\) 进行分讨。
若 \(k=1\),则根据基环树的定义,任连一条边即可,方案为 \(\dbinom{cnt_i}{2}-(cnt_i-1)\),减去的是原本就有的边。
若 \(k=2\),则任选两条连接两连通块的边连即可,方案为 \(\dbinom{cnt_i\times cnt_j}{2}\)。
若 \(k\ge 3\),我们需要先考虑环连接的顺序,即圆排列 \(\frac{1}{2}\times (k-1)!\)。这里需要乘一个 \(\frac{1}{2}\) 因为环同构的定义与排列循环相等的定义有别(可以顺逆时针反转)。然后我们考虑每个连通块之间怎么连边,发现一个连通块中点会贡献两次,所以这部分就是 \(\prod cnt_i^2\),乘起来就是 \(\frac{1}{2}\times (k-1)!\times \prod cnt_i^2\)。
基环计数完成后,还需要再乘上上面 Cayley 定理的那个式子。对于 \(k=1,2\) 的情况,我们发现直接枚举连通块即可,复杂度 \(O(n^2)\)。
对于 \(k\ge 3\) 的情况,我们需要维护 \(k\),连通块 \(cnt\) 之和,以及 \(cnt\) 之积。于是我们直接大力 dp,\(f_{i,j,k}\),代表 \([1,i]\),选择的基环连通块个数为 \(j\),\(cnt\) 之和为 \(k\),转移直接类似 01 背包大力维护乘完之后的贡献改变量即可。滚动数组优化后 \(O(n^3)\) 会超时,考虑继续优化。
由于 01 背包已经无法直接优化,我们考虑换着来枚举 \(cnt_i\) 拆贡献,考虑有哪些连通块集合包含 \(cnt_i\),这样可以把 \(cnt\) 之和一维去掉。现在多了一个属于的限制,于是我们令 \(f_{i,j}\) 代表 \([1,i]\),选择的基环连通块个数为 \(j\),考虑属于限制的集合贡献之和,同时令 \(g_{i,j}\) 代表 \([1,i]\),选择的基环连通块个数为 \(j\),不考虑属于限制的集合贡献之和。每次扩展一个数可以拆成属于和不属于两部分,分别用 \(f,g\) 更新,这样复杂度降为了 \(O(n^2)\),空间复杂度可以滚动变成 \(O(n)\),可以通过。
5.25 NOI 联考 T2 回滚
各种根号做法都比较难维护,定期重构也比较困难,考虑离线下来。
经典套路是看作二维坐标系,\(x\) 轴是时间维,\(y\) 轴是下标维,分别考虑几种操作在平面下的意义。操作 \(1\) 相当于对横轴为 \(t\),纵轴 \([l,r]\) 的矩形作区间加并加入,操作 \(2\) 相当于对横轴为 \(t\),纵轴 \([l,r]\) 的矩形作撤销,操作 \(3\) 相当于查询横轴 \([1,t]\),纵轴为 \(i\) 的矩形的前缀贡献。
考虑如何同时维护加入和撤销,这种栈问题一般考虑用左右括号刻画。对于 \(1\) 操作,我们给矩形加一个左括号,对于 \(2\) 操作,我们给矩形加一个右括号。那么如果横轴上一对括号被匹配了,那么这个左括号的贡献就没了。所以我们实际上是要求某纵轴上的一个前缀失配的左括号权值之和。
由于我们考虑的前缀在时间维上,考虑交换时间维、下标位,按原下标进行扫描线,\(l\) 位置加入左右括号,\(r+1\) 位置撤销左右括号,由于下标维原来是时间维,所以同时不可能有两个括号,每个新下标只会至多加入、撤销一次,所以这个是好维护的。
线段树每个结点存的是一段原时间区间的答案,需要维护区间内失陪左括号、右括号个数,失陪左括号权值和。pushup 的时候直接拿左区间的括号匹配右区间,作类似楼房重建的 \(\log n\) pushup 即可。总复杂度 \(O(n\log^2 n)\)。
QOJ 11111
Key Observation 1:若整个序列都 \(>1\),则直接选是更优的。
Key Observation 2:对于一段连续的 \(1\),要么全断开,要么整个连上。
我们将权值 \(>1\) 的极长连续段缩成一个点,将权值 \(=1\) 的极长连续段也缩成一个点,则原序列转换成了两种点交替出现的新序列,我们令新序列中每个点的权值为一个二元组 \((x,y)\),其中 \(x=\prod\limits_{i\in u}a_i,y=|u|\)。那么我们要决策的实际上是对于每个 \(=1\) 的点,是断开还是将左右两边的非 \(1\) 点连上。
Key Observation 3:若 \(\prod a_i>O(n)\),则直接全连上。
证明是考虑整个连的贡献实际上是 \(\prod a_i\),而每次替换得到的新贡献显然是 \(O(n)\) 的,解不等式可以得到。
Key Observation 4:点不超过 \(\log\) 个。
证明是判断了 Key Observation 3 后,乘积已经是线性级别的了,而对于一长度 \(len\) 的非 \(1\) 段,其二元组第一维的下界是 \(2^{len}\)。所以不会超过 \(\log\) 个这样的区间。
Key Observation 5:暴力做。
由于两种点是交替出现的,所以直接对 \(1\) 类点进行暴力,复杂度是正确的。
ARC162D
和联考基环比较像,但是还是做不出来啊。
考虑 prufer 序列的另一个形式:若有 \(k\) 个连通块,度数分别为 \(deg_1,deg_2,\dots,deg_k\),且 \(\sum deg_i=n\),则将这些连通块连成树的方案为 \(\frac{(n-2)!}{\prod\limits_{i=1}^kdeg_i!}\)。经过观察发现根和叶子一定是好结点,我们先直接对其贡献加上这个式子(注意根节点的 \(d_1\) 需要减一),接下来考虑其它结点的情况。
我们考虑对于一个结点 \(u\),有多少棵满足限制的树能对其造成贡献。假设我们现在从 \([u+1,n]\) 中选出了 \(k\) 个点,并要把它们插到 \(u\) 的子树中,根据度数的限制以及上面 prufer 序列的式子,这部分的方案是 \(\frac{(k-1)!}{(d_u-1)!\times \prod\limits_{i\in son_u} d_i!}\),子树外的方案只需将 \(u\) 子树「缩成」一个叶子做即可,这部分的方案是 \(\frac{(n-k-2)!}{(d_1-1)!\times \prod\limits_{i\notin son_u,i\neq 1}d_i!}\)。两部分乘起来得到 \(u\) 的贡献为 \(\frac{(k-1)!(n-k-2)!\times d_1\times d_u}{\prod\limits_{i=1}^nd_i!}\)。
我们还需要统计 \([u+1,n]\) 有多少种这样的子树选法。由于这个式子只和 \(k\) 有关,我们设计一个三维 dp,\(f_{i,j,k}\) 代表考虑 \([i+1,n]\) 中的数,目前选了 \(j\) 个点,度数之和为 \(k\) 的方案数(第二维是为了方便转移)。dp 完之后每次枚举 \(i,k\),拿 dp 权值乘上式子即可。复杂度三次方。
P11750 「TPOI-1D」谢谢您。
和出现次数有关的处理方法通常是根号复杂度的,不难发现可以先按照 \(k\) 的出现次数根号分治一下。
若 \(cnt_k>\sqrt n\),则这样的 \(k\) 不超过 \(\sqrt n\) 个,离线下来后直接暴力统计 \(k\) 在每个区间的出现次数,线段树维护 rmq 即可。
若 \(cnt_k<\sqrt n\),似乎不太好处理。我们可以枚举其每个出现位置,然后考虑左端点在当前点左侧的所有区间,取右端点的 \(\max\) 即可不漏的取到答案,即 \(\max\limits_{a_{p_i}=k}\max\limits_{L\le j\le R,l_j\le k}r_j\)。这是一个 3-side 的矩形限制,考虑在这 \(<\sqrt n\) 个出现位置上都挂上该次询问,离线后扫描线。
现在问题转换成一个有单点改的 rmq。仔细分析下发现有 \(O(n\sqrt n)\) 次查询,\(O(n)\) 次本质不同的修改。这个看起来十分困难,因为你不能 \(O(n\sqrt n\log n)\),不过仍然还是有非常具有启发性的做法的。
借鉴 Four Russians 的思想,对当前序列分块,每个块内维护一个 st 表,块间维护一个 st 表。查询时可以做到 \(O(1)\),难点在于修改。不过注意到,一次单点修改,其实不会对很多表里的值造成影响。我们考虑 \(j\) 的贡献,即有多少 \(i\) 满足 \(st_{i,j}\) 发生了变化,此时 \(i\) 的一个限制是 \(x-2^j+1\le i\le x\),也就是说 \(j\) 的贡献至多是 \(2^j\) 的,所以总共产生的影响是 \(O(\sum2^i=2^{\log \sqrt n}=\sqrt n)\)。直接维护即可。
总复杂度精细实现可以做到 \(O(n\sqrt n)\)。
CF1726E Almost Perfect
排列计数,直接维护不太好做,将其映射到排列置换环,变成环计数。
众所周知,对于一对互为逆的排列 \(p_i\) 和 \(q_i\) 满足在置换环上分别是 \(i\) 的后继和前驱,即 \(p_i,q_i\) 存在一条距离为 \(2\) 的简单路径。限制转换成,要求环上每隔两个点的编号差 \(\le 1\)。经过手模发现,符合要求的单环,只有自环、二元环、和四元环。由于环上奇偶位置是独立的,所以可以归纳证明除了这三种情况之外其它长度的环不可能满足限制。限制转换成,将 \(n\) 个点划分成若干自环与二、四元环,满足四元环距离为 \(2\) 的点的编号之差 \(\le 1\)。根据奇偶位置的独立性,四元环这里只需要找到两对不重的相邻数对,拼起来即可。
具体来说,我们枚举四元环的个数,然后排列组合选若干个相邻数对,并乘上其组成四元环的方案(其实就是 \(2\) ),最后乘上自环、二元环的计数(这部分可以线性递推,\(f_i=f_{i-1}+(i-1)\times f_{i-2}\))。
CF1062F Upgrading Cities
直接可达性统计是 \(O(\frac{nm}{w})\) 的,无法通过。
我们将 \(n\) 个点按照拓扑序排序,并以此处理。根据 DAG 的性质,如果一个点在时刻 \(t\) 被加入队列,那么说明它无法到达之前在队列里的点,对于它后面加入队列的那些点也同理。所以一个点能满足要求的充要条件时,前面的点都能到达它,它都能到达后面的点。
由于前缀和后缀同理,这里只考虑前缀。我们从前往后扫点,并且只维护 \(dfn_1,dfn_2,\dots,dfn_i\) 所构成的前后缀子图。能够判断是否可达 \(i\) 的充要条件是,前面的点在当前子图中出度都不为 \(0\)。因为这是个 DAG。每次加入的边的总和是 \(O(m)\) 的,直接维护当前出度并判断即可。
对于那个允许更弱的计数,相当于是找到前后缀唯一的那个出度为 \(0\) 的点,将其删掉。我们用 std::set 维护这个点,并维护连接这个点的出度为 \(1\) 的点的数量,因为如果我们删掉这些点,连接这个点的那些点的出度也会减 \(1\),有可能因此而寄掉。
CF475E Strongly Connected City 2
经典的耳分解起手,E-BCC 可以通过定向转为 SCC。所以边双缩树后每个点内部的贡献是点权的平方。
我们不难发现,如果我们钦定一个点为树根,那么让一部分子树自下往根运输,一部分子树自根往下运输,一定是最优的(相当于将根当作中转点)。又是一个经典的最大化两部分点权和乘积问题。考虑对该层儿子做背包 dp 维护可行性,直接硬取 \(\max\) 即可。\(O(n^2)\) 可过。这里不需要那个 \(\frac{n\sqrt n}{w}\) 的优化,据说还有神秘多项式做法。
P9829 [ICPC 2020 Shanghai R] Traveling Merchant
转换题意。有黑点和白点,只能走交错路,每到一个点这个点颜色取反,求是否能从 \(1\) 走到环上。
观察发现,我们的路径是由 \(1\rightarrow u\rightarrow v\rightarrow u\dots\) 这样的形式构成的。注意到第一次走到 \(u\) 的时候颜色取反了,所以 \(u\) 和 \(v\) 的颜色不能相异,反而应该相等。其它边的颜色则都应该相异。注意到这个同色边很特殊,所以我们需要考虑枚举这种边,问题转换成对于一条同色边,能否只通过异色边从 \(1\) 到 \(u\),从 \(u\) 到 \(v\)。
由于剩下我们只能走异色边,不妨先把同色边扔掉,只建出关于异色边的图,然后挨个考虑同色边。相当于判断是否存在这样的路径。这个图没啥启发性,但是我们可以缩点双,建圆方树,这样路径判断就转换成了 \(u\) 和 \(v\) 所对应的那个点双分量,是否成祖孙关系,这个是不难证明的。于是我们预处理出圆方树上方点的 dfn 序,判断区间是否有交即可实现祖孙关系判断。复杂度线性。
CF1753C Wish I Knew How to Sort
难在状态设计。考虑到排完序后显然是一段连续的 \(0\) 加上一段连续的 \(1\),只要确定了其中一种值的位置就可以确定全部。所以我们的状态不妨对前缀 \(0\) 的个数进行设计。令 \(f_i\) 代表当前序列在原本 \(0\) 的连续段的位置中填了 \(i\) 个 \(0\) 的期望次数,我们有 \(f_{cnt_0}=0\),且答案为初始状态下 \([1,cnt_0]\) 中 \(0\) 的个的 \(f\)。考虑如何转移,这个是容易的,考虑上一次交换是交换了 \([1,cnt_0]\) 中的一个有效 \(1\) 还是无效的交换。直接转移即可。形如 \(f_i=1+p\times f_i+(1-p)\times f_{i+1}\)。
另一种解释是,注意到每次交换中前缀 \(1\) 的个数其实等于后缀 \(0\) 的个数,所以每次成功交换的概率是 \(\frac{x^2}{C_n^2}\) 的,那么只需要考虑一开始前缀有多少个 \(1\) 即可。答案为 \(\sum\limits_{i=1}^{cnt} \frac{C_n^2}{x^2}\)。
AGC019F Yes or No
考虑最优策略实际上是什么。假如当前状态下你已知还剩下 \(n\) 个 YES,\(m\) 个 NO,若 \(n>m\),则此时回答 YES 答对的概率 \(\frac{n}{n+m}\) 大于回答 NO 答对的概率 \(\frac{m}{n+m}\),所以你肯定是要回答 YES 的。\(n<m\) 同理。对于 \(n=m\) 的情况,此时随便问,有 \(\frac{1}{2}\) 的概率答对。
直接记这两维 dp 是没有前途的。使用二维坐标系刻画这个策略,构造一个 \(n\) 列 \(m\) 行的网格图。我们画出 \(y=x\) 这条直线,则策略转换成,当前点坐标在 \(y=x\) 上方,则回答 NO,在下方则回答 YES,否则随机回答。我们将 \(y=x\) 上方的折线翻折下去,发现上方和下方的贡献一定为 \(\max(n,m)\)。现在我们只需要考虑和 \(y=x\) 部分重合的那部分额外贡献的情况了。根据期望的线性性,对于对角线上任意一个点 \((x,x)\),到达这里的概率为 \(\frac{C_{2\times x}^x\times C_{n+m-2\times x}^{n-x}}{C_{n+m}^n}\),答对的概率为 \(\frac{1}{2}\)。只需把这两个东西乘起来再求和,最后加上 \(\max(n,m)\) 则为最终的答案。
ARC150D Removing Gacha
一个点可能被选多次,考虑直接根据线性性拆贡献。拆 \(E_i\) 代表选 \(i\) 这个点的期望次数,答案就是 \(\sum\limits_{i=1}^n E_i\)。考虑一个点什么时候一定停止被选,其实就是当且仅当其祖链上所有点都被选过了。发现比较难处理的其实是每次的样本空间受限,经典技巧是把样本空间扩大,并只在部分计算贡献。此时 \(E_i\) 转换成,每次随便选祖链上的一个点,但是只有选到 \(i\) 时贡献加一,所有点都被选时停止的期望贡献。这个和原问题是等价的。
考虑当前已选了祖链上的 \(x\) 个点,令祖链长度为 \(deep_i\),则此时新选一个点的概率为 \(\frac{deep_i-x}{deep_i}\),所以新选一个点的期望次数为 \(\frac{deep_i}{deep_i-x}\)(不针对某个点考虑,而是考虑「增加点」事件的期望)那么全部选好的期望次数就是 \(\sum\limits_{i=0}^{deep_i-1}\frac{deep_i}{deep_i-i}=deep_i\times \sum\limits_{i=1}^{deep_i}\frac{1}{i}\)。现在考虑那个贡献,选中我要的这个点的概率是 \(\frac{1}{deep_i}\),所以最后期望贡献要乘上这个,得到 \(E_i=\sum\limits_{i=1}^{deep_i}\frac{1}{i}\)。最后全部加起来。
CF1096E The Top Scorer
本质上是先把概率拆掉,然后根据数据范围考虑可以枚举的东西。
枚举那个 \(\ge r\) 的人的分数 \(x\),求出 \(x\) 成为冠军的概率。我们将剩余 \(p-1\) 个人分成两类,一类是分数小于 \(x\) 的,另一类是分数等于 \(x\) 的。枚举 \(p-1\) 个人中分数等于 \(x\) 的人数 \(y\),则这部分的贡献为 \(C_{p-1}^y\times \frac{1}{y+1}\)。接下来考虑剩下 \(p-y-1\) 个人的贡献,由于和一定,则问题转换成,要给 \(n\) 个人分配分数,要求 \(\sum=s-(1+y)\times x\),同时限制是每个人的分数不能超过 \(x-1\)。
这是一个经典的容斥,由于上界相同。直接交集变全集减去补集的并,然后容斥补集,转换成有下界的单线性方程非负整数解,这个是容易做到的。
所以计数部分就完成了,考虑概率如何算。在我们枚举 \(x\) 的同时,维护一个全集,同样是单线性方程非负整数解,加上个组合数即可。最后拿计数的结果除以这若干个组合数的和就是要求的概率。
CF1712E2 LCM Sum (hard version)
反过来做,减去 \(lcm(i,j,k)<i+j+k\)。这类三元组比较稀缺,不妨考虑它们的共同点。令 \(lcm(i,j,k)=xk\),不难发现 \(x=1,2\) 时条件才可能成立,同时 \(x=2\) 时需要满足 \(i+j<k\)。分别对这两类情况计数,第一类 \(lcm(i,j,k)=k\),将 \(n\ln n\) 个 \((i,k)\) 二元组存下来,权值为中间有多少 \(j\)。查询时本质在查有多少满足 \(l\le i,k\le r\) 的二元组的权值和,扫描线 BIT。第二类 \(lcm(i,j,k)=2k\) 且 \(i+j<k\),通过数学推导可以发现这样的 \(i,j,k\) 的比例是固定的,直接数学公式推导 \(O(1)\) 查询即可。
APC001F XOR TREE
每次修改的是一条链,修改的边太多不太好刻画,且传统的树上差分也无能为力。
一个不太容易想到的点是边权转点权,令 \(val_i=\bigoplus\limits_{e(u,v),u=i\lor v=i}w(u,v)\),即点的所有邻边的异或和。这么转换后好处明显了起来,修改一条链可以直接转换成修改两个点,同时边权和为 \(0\) 也等价于点权和为 \(0\)。
第二个不太容易想到的点是 观察到 \(a_i\le 15\),我们可以统计处每个 \(a_i\) 的出现次数,由于每次操作只改了两个点权,我们只要拿两个相同的点权互相做就可以抵消。所以这部分的消耗是 \(\sum\limits_{i=1}^{15}\left\lfloor\dfrac{cnt_i}{2}\right\rfloor\)。
现在,我们只需要考虑那些剩下来的余数。此时 \(n\le 15\),而由于每次操作至少可以干掉一个点权,所以答案至多为 \(15\)。可以直接枚举子集 dp。
QOJ7330 Territory Game / 6.1 NOI 联考 T1 染色游戏
若 \(k>dis(x,y)\),可以直接判掉,答案为 \(k\bmod 2\)。
若 \(k\bmod 2=0\),后手具有最后走一步的优势,所以会考虑「乘胜追击」,向先手靠。若 \(dis(x,y)\bmod 2=1\),先手可以采取同样的策略来最小化损失,此时答案为 \(0\)。否则先手考虑逃避(否则就变成 \(-2\) 了),需要找到一条长度至少为 \(\frac{k}{2}\) 的路径,不能与正在往这边靠的后手相交,成功则为 \(0\),否则为 \(-1\)。
若 \(k\bmod 2=1\),先手具有最后走一步的优势,所以会考虑「乘胜追击」,向后手靠。若 \(dis(x,y)\bmod 2=0\),后手可以采取同样的策略来最小化损失,此时答案为 \(1\)。否则后手考虑逃避(否则就变成 \(2\) 了),需要找到一条长度至少为 \(\frac{k-1}{2}\) 的路径,不能与正在往这边靠的先手相交,成功则为 \(1\),否则为 \(2\)。
问题转换成,如何快速维护逃避的过程,即快速判断出是否存在这样一条路径。我们如果称先后手往这边靠的这条路径被我们 ban 掉了,则相当于我们不能走被 ban 掉的地方。手模发现,被ban 掉的地方,要么形成子树,要么形成子树外面的整片区域,根为路径的最后一个点。我们求出这个点之后,找到没被 ban 掉的区域(同样为子树或子树外)的 \(x\) 的最长路。
根据常识,这个某个点的最长路实际上就是某直径端点。也就是说,我们需要维护子树内部的直径端点以及子树外部的直径端点。
两种做法,第一种是删掉一条边后求两部分直径,可以树形 dp,另一种是拆成 dfn 区间,线段树维护可并直径四选二即可。
CF1305F Kuroni and the Punishment
Obvious Observation:选择钦定的 \(\gcd\) 一定是质数。
Key Observation 1:答案不超过 \(n\)。钦定 \(\gcd =2\) 即可做到这一点。
Key Observation 2:有一半以上的元素的最终改动变化量 \(\le 1\)。否则改动变量量 \(>\frac{n}{2}\times 2=n\),矛盾。
考虑随机化,枚举 \(x\) 个元素并对它们质因数分解作为最终可能作为答案的 \(\gcd\)。然后一个个判,取 \(\max\)。
我们发现,只需要取 \(x=30\) 个元素就完全可过,因为根据性质 2,每个元素成功的概率是一半,那么错误的概率只有 \(\frac{1}{2^{30}}\)。
CF196E Opening Portals
感觉很有道理但是一开始想错了,需要注意这个建模和斯坦纳树的本质区别是该题一条边是可以经过多次的。
将建模拆成两部分,一部分是 \(k\) 个传送门内部,另一部分是 \(1\) 走到其中一个传送门。第一部分就是考虑 \((u,v,dis(u,v))\) 这么连边然后跑完全图的最小生成树,第二部分就是 \(1\) 到最近传送门的距离。复杂度瓶颈在于第一部分,是 \(O(n^2\log n)\) 的,不可过。
考虑将不可能作为最小生成树上的点抛去。对于一条边 \((u,v,w)\),找出距离 \(u,v\) 最近的两个传送门 \(u',v'\),则连边 \((u',v',dis(u'u)+dis(v',v)+w)\)。可以证明这样跑出来一定能覆盖所有的最小生成树上的边。这样复杂度降为 \(O(n\log n)\)。
CF1253F Cheap Robot
懂了上面那个题之后这个题就直接会了啊。
考虑充电站和充电站之间连边,边权为全源最短路的值。那相当于是从一个充电站到另外一个充电站,最小化最大边权。这是一个经典问题,考虑瓶颈路变 kruskal 重构树、最小生成树,求 LCA 即可。
不能直接连完全图,还是考虑删掉那些不可能在树上的边,每条边找离端点最近的两个充电站之间连边即可。复杂度降为 \(O(n\log n)\)。
CF1844G Tree Weights
很巧妙的按位构造。我们已知 \(i\) 和 \(i+1\) 的距离,要还原出所有边。而距离是和 \(dis(1,i)\) 挂钩的,启示我们求出每个 \(dis(1,i)\),再通过相减得到所有边权。考虑把距离的式子写出来 \(ans_i+ans_{i+1}-2\times ans_{lca(i,i+1)}=d_i\),其中 \(ans_i=dis(1,i)\)。我们现在已知 \(ans_1=0\),要递推出所有的 \(ans_{i+1}\)。但是由于 \(lca\) 存在,这个转移不一定是个 DAG,我们要想办法将 \(lca\) ban 掉,或者先求出它。
考虑按位构造,我们先考虑求出所有 \(ans_i\bmod 2\) 的值。由于 \(lca\) 那项系数前有个 \(2\),所以不用考虑,直接就被 ban 掉了。现在我们已知了所有 \(ans_i\bmod 2\) 的值,考虑求出所有 \(ans_i\bmod 4\) 的值。由于 \(lca\) 那项系数前有个 \(2\),所以只需要考虑其模 \(2\) 的值,而这个东西上一次已经求出来过了。以此类推,我们已知按照 \(\bmod 2^i\) 考虑,直到 \(2^i\) 充分大即可。
QOJ9479 And DNA
首先原题的限制相当于对是环上任意相邻三点的限制。
考虑拆出每一位计数,设当前考虑的是第 \(i\) 位,我们根据 \(m_i\) 的值进行分讨。
若 \(m_i=0\),则相邻三点可以是 \((0,0,0),(0,0,1),(1,0,0),(1,1,1)\),其中最后一种代表进位。经过观察后发现,\((0,0,1)\) 和 \((1,0,0)\) 不能存在,因为当相邻三点转动时你就寄了。所以结论是此时只能全填 \(0\) 或全填 \(1\)。
若 \(m_i=1\),则相邻三点可以是 \((1,0,1),(0,1,0),(0,1,1),(1,1,0)\),经过观察后发现,这四种情况在 \(n>3\) 的情况下都有可能被填,且需要特判一下 \(n=3\) 时,只有 \((0,1,0)\) 不能被填,因为此时经过一次转动会转换成 \(m_i=0\) 的情况 \((1,0,0),(0,0,1)\)。
接下来考虑如何 dp。按位 dp 的一个通常比较让人头疼的点是,处理进位。但是由于这道题独特的性质(进位是全填 \(1\))我们发现实际上并不会出现两个相邻三点的进位情况不一样的情况,所有相邻三点都是同时进位的。我们直接对每一位这个整体进行 dp。
令 \(f_{i,0/1,0/1}\) 代表当前考虑到了 \(m\) 的 \(0\) 到 \(i\) 位,强制第 \(i\) 位的相邻三点填 \(0/1\) 所对应的的情况,且填完之后有无进位的方案数。(这里的状态稍微设置不当就可能会导致进位产生后效性,所以尽量维护多而恰当的信息)
考虑根据 \(m_i\) 这位的值来设计转移,这里我们令 \(cost\) 代表填 \(1\) 所对应的情况的方案。(这里每一位没有区别)
若 \(m_i=1\),则有 \(f_{i,1,0}=(f_{i-1,1,0}+f_{i-1,0,0})\times cost\),\(f_{i,0,0}=f_{i-1,1,1}+f_{i-1,0,1}\),\(f_{i,0,1}=f_{i-1,1,1}+f_{i-1,0,1}\),\(f_{i,1,1}=0\);\(m_i=0\) 同理。基于进位和要填的数转移即可。
现在考虑如何求出 \(cost\),虽然这里的转移是在环上的,但是我们只需要转移 \(n\) 次,并取出那个和初始状态相同的 dp 值。我们令 \(g_{i,1/2/3/4}\) 代表考虑到了 \(1\) 到 \(i\)(根据上面的说法,可以直接不考虑环,从 \(3\) 转移到 \(n+3\))且最后相邻三点的状态为钦定的方案数。直接转移是 \(O(n)\) 的,但是由于转移是线性的,可以直接挂在矩阵上,跑矩阵快速幂。
总复杂度 \(O(\log n)\)。
CF1830C Hyperregular Bracket Strings
想问题应该先弱化问题。
考虑当只有一个区间限制的时候,我们可以将原序列拆成两段 \((1,l-1) \bigcup (r+1,n) ,(l,r)\)。分别做 Catalan 再乘起来。这么做是很有道理的,因为区间外的左括号一定跟区间外的右括号匹配。当有两个相交的区间限制是,我们发现相交的那段应该也是合法的。因为若相交一段的某个左括号的匹配在右端点更大的区间内,则另外一个区间就会失配。
我们令 \(S_i\) 代表将 \(i\) 覆盖的区间集合,则根据上面的推论,\(S\) 相等的这些点应该是合法的,不难证明这个的充要性。问题转换成如何维护 \(S_i\),直接维护下标显然没有前途。考虑哈希,考虑到一段 \(S\) 相等的点是一段区间,所以可以给每个区间赋随机权然后区间异或差分,使用异或哈希。回答时把哈希出现次数塞到 map 里即可。
P10016 [集训队互测 2023] 虹
卡常的恶心题。
首先不太容易地注意到 \(19901991\) 是 \(2042024\) 的二次剩余,所以我们只需维护 \((z_{\gcd(i,u)}\times w_i)\bmod 2\) 的值。\(\bmod 2\) 可以联想到 bitset,结合数据范围和要维护的东西的复杂程度基本上能够确定。相当于我们维护 \(Z_1,Z_2,\dots,Z_n,W\) 这些 bitset,对于一组询问我们直接将 \(Z_u\) 和 \(W\) 做按位与,根据 \(\bmod 2\) 的性质 popcount 就是答案。分别考虑如何维护 \(Z_i\) 和 \(W\)。
对于 \(W\),我们需要维护修改操作,即对 \([l,r]\) 的最小虹加一。不难发现最小虹等价于不缩点的虚树,根据结论我们求出 \(i\in [l,r]\) 的根链路径并,最后抛去 \(lca(l,r)\) 的父亲的根链路径即可。我们令 \(p_i\) 代表 \(i\) 的根链路径,后面那个 \(lca\) 父亲是好处理的,直接 xor 一下。如何处理一段区间的 \(p\) 的并?考虑分块,散块暴力算,整块区间预处理。这里有一个必要的剪枝是,我现在要加入一个点 \(i\) 的贡献,在跳父亲的时候如果这个父亲已经被标记过了,就可以直接跳过了。通过这个剪枝可以保证暴力的复杂度均摊是 \(O(\frac{n^2}{w})\) 的。对于端点在同一块内的区间,只能 \(O(n)\) 暴力算。注意到数据随机,我们缩小块长令 \(B=\frac{n}{\sqrt q}\),根据随机的概率这样整体的复杂度是最优的。
对于 \(Z_i\),相当于要维护一个 \(Z_{\gcd(i,j)}\) 的 01 矩阵。这个似乎不太能直接维护的了,考虑枚举每个质因子以及其出现次数,暴搜出每一个数,每次乘上一个质数,更新其 \(\gcd\) 的贡献以及 \(Z_i\)。经过神秘计算,这个东西的计算次数为 \(O(可过)\)。
但是现在还仍然有很多问题没有解决。首先空间上我们只能开一个 \(\frac{n^2}{w}\) 的 bitset。在暴搜的过程中,我们只能维护当前 \(i\) 的 \(Z\),不可能都存下来。于是我们考虑将询问都离线下来,\(Z\) 只开一个,维护当前暴搜状态下的那个 \(Z_i\)。在暴搜中处理询问。但是如何同时维护修改操作呢?考虑对于每一个时间戳,维护一个当前状态下的 \(W'\),也就是说我们将 \(W\) 扩展了大小为 \(q\) 的一维。暴搜里查询的时候找到该时间戳对应的 \(W'\) 即可。
如何维护 \(W'\) 呢?根据刚刚的分块操作,我们还需要维护块内根链路径并,散块前缀路径并,单点路径并。显然空间爆完了。考虑同样对 \(W\) 进行类似二次离线的操作。对于一个散块的前后缀根链路径并,直接把询问挂在左右端点上,每次求出前后缀散块路径并时再 or 上对应的询问即可。对于若干整块的根链路径并,由于块长变小了,所以直接枚举每个块会爆。考虑当 \(q\) 小的时候直接做,否则令 \(b_{i,j}\) 代表第 \(i\) 块到第 \(j\) 块的答案,预处理这个 \(b\)。但这样空间又爆了,于是同样对整块也离线下来,询问挂在 \((i,j)\) 上,跟散块处理方法一致,只需开一个 bitset 即可。
P2305 [NOI2014] 购票
我们首先有一个 \(O(n^2)\) 的转移:\(f_x=\min\limits_{x\in son_y,dis_x-dis_y\le l_x}f_y+(dis_x-dis_y)p_x+q_x\)。这种式子一看就很斜率,但是由于无法保证 \(p\) 的单调性,没法直接做。
大力考虑李超树。将转移改为 \(y=kx+b\) 的形式,即 \(f_x-dis_xp_x-q_x=\min(-dis_yp_x+f_y)\)。每次我们算完一个 \(f\) 就把 \((-dis_x,f_x)\) 丢进李超树里面。查询时直接在李超树里查。
但我们还没有解决 \(dis_x-dis_y\le l_x\) 的限制,可以通过倍增找出深度最小的符合要求的 \(x\) 的祖先 \(y\),然后相当于要维护这段路径的李超树,显然只能树套树了。但是直接树剖是 \(\log^3\) 的,不太行。考虑 dfn 的出栈序,由于出栈序的优秀性质(子树内小于该点,编号项右递增)我们发现 \(x\) 到 \(y\) 的 dfn 出栈序其实是连续的一段,于是可以把树剖的一个 \(\log\) 省掉。同时由于我们只需要在李超树插入查询直线,所以可以 zkw 线段树。
P11364 [NOIP2024] 树上查询
直接 dfn 序区间 \(lca\) 没有什么前途,同时刻画 \(\min,\max\) 比较困难。考虑那个虚树的结论,\(deep_{lca(l,r)}=\min\limits_{i=l}^{r-1}deep_{lca(i,i+1)}\)。这样我们只需刻画 \(\min\) 了。
考虑把单调栈搞出来,求出每个 \(deep_{lca(i,i+1)}\) 所能贡献到的极长连续段 \((x_i,y_i,v_i)\),\(v_i\) 代表其价值即 \(deep_{lca(i,i+1)}\)。相当于要求,和 \([l,r-1]\) 交集至少为 \(k-1\) 的极长连续段权值的 \(\max\)。先把 \(l=r,k=1\) 判掉。
考虑分两种情况讨论,\(r\le y_i,r-k+1\ge x_i\),和 \(l+k-1\le y_i\le r,y_i-x_i+1\ge k\)。考虑分别对 \(r,k\) 做扫描线,由于 \(\max\) 的可重复贡献性,即可不漏的计算答案。复杂度为 \(O((n+q)\log n)\)。
P11993 [JOIST 2025] 迁移计划 / Migration Plan
bfs 序转区间是没有前途的,因为线段树合并不能直接合并两段不等长的区间,所以不太能每个点都直接维护。
考虑一些智慧的东西。每次合并的时候不直接对位合并,而是直接把 \(deep=x\) 的集合整个合并到 \(deep=y\) 的集合上,这里直接把对位扔掉。
考虑查询的过程,实际上就是考虑那些子树内的修改,由于所有的修改都被你全提到当前 \(deep\) 所对应的集合上了,所以问题转换成集合内子树贡献求和,直接下标 dfn 序,区间求和即可。
综上,每个深度维护一棵以 dfn 序为下标的线段树,合并操作直接线段树合并,修改操作单点改,单点查询直接求该点深度对应的那棵线段树的子树 dfn 区间和。
CF1188C Array Beauty
枚举美丽值 \(k\)。
我们先想办法去掉绝对值,观察到将数组打乱顺序不会影响答案,我们不妨将 \(a\) 排序,这样即可去掉绝对值。
令 \(f_{i,j}\) 代表 \([1,i]\) 中选了 \(j\) 个,强制选 \(i\) 的答案。由于「任意两元素差」不太好刻画,套路地转换成任意两元素差 \(\le k\),然后差分一下即可。
转移直接枚举 \(a_i-a_x\le k\),由于数组有序,所以转移构成单调的连续段,双指针+前缀和即可做到 \(O(nk)\)。
现在复杂度为 \(O(nkV)\),无法通过。考虑缩减枚举美丽值的范围,发现美丽值至多取到 \(O(\frac{V}{k})\)(贪心地最大化间隔),所以只需枚举合法的美丽值,复杂度 \(O(\frac{V}{k}\times nk)=O(nV)\),可以通过。
P6790 [SNOI2020] 生成树
直接做很难做到优秀复杂度,无法硬上矩阵树定理。考虑原图的特殊性质,一棵仙人掌加上一条边,不难猜想原图是广义串并联图。考虑如何证明,根据之前的结论,仙人掌选出四个点后至多有四条连接两点的路径不交,加上一条边后,至多有五条连接两点的路径不交,所以猜想正确。
既然我们已知原图是广义串并联图,考虑利用那三种操作缩图。由于生成树的不同取决于选择的边集,不难想到把计数挂在边上,对于每一条边,令 \(f_i,g_i\) 分别代表选不选这条边对答案的贡献。
对于删 \(1\) 度点,我们令 \(ans=ans\times f_e\)。
对于缩 \(2\) 度点,我们令 \(f_{e'}=f_{e_1}\times f_{e_2}\),\(g_{e'}=f_{e_1}\times g_{e_2}+g_{e_1}\times f_{e_2}\)。这里不算 \(g_{e_1}\times g_{e_2}\) 是因为生成树不可能同时不选这两条边。
对于叠合重边,我们令 \(f_{e'}=f_{e_1}\times g_{e_2}+g_{e_1}\times f_{e_2}\),\(g_{e'}=g_{e_1}\times g_{e_2}\)。这里不算 \(f_{e_1}\times f_{e_2}\) 是因为生成树不可能同时选这两条边。
直接模拟 bfs,队列里维护所有 \(deg\le 2\) 的点即可。使用 unordered_map 等方法精细处理可理论上做到线性。
P8426 [JOI Open 2022] 放学路 / School Road
一眼感觉这个条件很稀疏啊,稍微复杂一点的图基本就能满足要求。我们不妨先钦定原图是点双。
部分分中有一个 \(|E|-|V|\le 13\),这启示我们考虑广义串并联图。这个部分分只需按照上面叙述的缩图方法暴力即可,考虑更加一般的情况。假如原图存在一个同胚于 \(K4\) 的子图,令其为 \((a,b,c,d)\),不妨先假设原图答案为不存在。取出两条路径,由于不存在一条大于最大路的简单路径,所以两条不同路径的长度相等,取出这样的路径后可以得到 \(w(a,b)=w(a,d)+w(d,b)\),\(w(a,d)=w(a,b)+w(b,d)\),可以发现 \(w(b,d)=w(a,b)-w(a,d)=w(a,d)-w(a,b)=0\),与边权为正矛盾。因此若原图不是广义并串联图则一定有解。
考虑原图是广义串并联图的情况。仍然考虑删 \(1\) 度点、缩 \(2\) 度点、叠合重边。删 \(1\) 度点对答案没有影响,这里注意一下不能删 \(1\) 和 \(n\),缩 \(2\) 度点时,我们将新边边权设为原来的两条边边权之和,叠合重边的时候,我们可以将边权设为负无穷。
对于最后的答案,我们考虑是否只剩 \(1,n\) 且仅存在一条边、这条边是否为负无穷即可。
现在考虑如何处理非点双的情况,经过大量手模、感性猜测可以得出,若 \(1\) 和 \(n\) 点双连通可以直接缩、否则多连 \((1,n,w(1,n))\) 不会影响答案并可以满足点双连通,按照上面的方法处理即可,这里不再赘述。详细的证明比较冗余、复杂。
P5391 [Cnoi2019] 青染之心
建树不难看出。如何统计根链的完全背包?直接做时间复杂度没问题,但是空间炸了。考虑类似 ddp 的优化方式,我们先维护轻儿子,最后再求重链。状态改为 \(f_{dep,i}\),\(dep\) 代表根链所经过的重链条数即可,轻儿子更新时直接 \(dep+1\),否则用已经求过的 \(dep\) 覆盖。
CF498C Array and Operations
注意到贪心地让除的次数尽可能多,那么选择去除的数一定是质数。
我们发现每个质因子的贡献都是独立的,所以考虑将每个质因子分开考虑,我们先求出每个 \(a_i\) 中包含当前质因子 \(p\) 的次数 \(b_{i,p}\)。
考虑如何建模。由于保证每条边的 \((u+v)\bmod 2=1\),一个套路是考虑将原序列划分成奇偶两部分,这样就转换成了一个二分图。
具体来说,建源汇点 \(s,t\),\(s\) 向所有 \(i\bmod 2=1\) 连边,流量为 \(b_{i,p}\);\(t\) 向所有 \(i\bmod 2=0\) 连边,流量为 \(b_{i,p}\),原图中左部点向右部点连边,流量为 \(\min(b_{u,p},b_{v,p})\)。直接跑最大流即可。
P7360 「JZOI-1」红包
看到这种式子知道大概离反演不远了。但是 \(\operatorname{lcm}\) 没法直接莫反。
结合 \(\min-\max\) 容斥,可以类比出 \(\gcd-\operatorname{lcm}\) 反演,即 \(\operatorname{lcm}(S)=\prod\limits_{u\subseteq S}\gcd(U)^{-1^{|U|+1}}\)。
推式子,然后直接拆贡献莫反。
这个题的 trick 是,当出现一个长的很像二项式的东西出现时,可以通过改变某项的次数来凑成二项式定理的形式。
在本题中,直接考虑求原答案的倒数,结合补项就可以出一个二项式定理,剩下的直接整除分块就行了。
总复杂度 \(O(T\sqrt n\log n)\)。
神秘模拟赛 T4 美味的派
简单题。
我们将原问题转换成一个图,其中左部点是牛 \(A\) 的派,右部点是牛 \(B\) 的派。考虑左部点 \(i\) 向右部点 \(j\) 连边,当且仅当 \(|a_i-a_j|\le D\)。然后我们把所有 \(a_i=0\) 的点拎出来,跑最短路就行了。
考虑怎么优化这个过程,注意到派的相对顺序实际上并不重要,我们将派按照 \(a_i\) 排序,直接线段树优化建图即可。
P11672 [USACO25JAN] Table Recovery S
?
Key Observation 1:整个表中,只有 \(2\) 和 \(2n\) 出现了恰好一次。
Key Observation 2:对于任意点,其所属行、所属列,数构成的集合是同构的。
Key Observation 3:除两个出现一次的数外,其它数出现次数不同。
考虑用出现次数刻画位置。根据 Key Observation 2,经过操作 \(1\)、操作 \(2\) 后,行和列所属集合没有变化,或者说是原表的一个排列。我们先找出出现次数为 \(1\) 的数的位置,然后利用出现次数的不同来填出整个表。
不难发现因为出现次数为 \(1\) 的数有两种,因此我们填两次表,取字典序最小即可。这同时也说明了答案的唯二性。
P3552 [POI 2013] SPA-Walk
我们称「两 01 串之间连边当且仅当存在位不同」所形成的图为 \(n\) 维超立方体。我们有结论,若将 \(n\) 维超立方体划分成两个点集,大小分别为 \(x,y\),则两点集之间的连边一定 \(\ge \min(x,y)\)。由此我们可以得出推论,删除 \(k\) 条边后,至多有一个连通块大小 \(\ge nk+1\),证明是若存在两个这样的连通块,则一定要删至少 \(nk+1\) 条边,然而你 ban 掉一个点最多删掉 \(n\) 条边,因此你只能删 \(nk\) 条边,矛盾。
有了这个结论后,我们对其中一个起点 dfs 直到找到终点或 dfs 了 \(nk+1\) 个点,此时我们只需要对终点 dfs 看其是否也能 dfs 到 \(nk+1\) 个点即可。复杂度 \(O(nk)\)。
P3765 总统选举
注意到绝对众数在序列中的出现次数要超过一半,因此我们如果从序列中均匀随机一个数作为绝对众数的概率至少为 \(\frac{1}{2}\),由此我们可以多随机几次,每次随一个数并判断其出现次数是否满足要求即可。大概随机 \(14\) 次左右错误率就达到了 \(\frac{1}{2^{14}}\)。求区间内出现次数可以主席树或者每种颜色维护一棵平衡树。
P5642 人造情感(emotion)
维护三元组标记的做法比较冗余,事实上由于我们的路径经过 \(u\) 且不经过 \(v\),显然 \(deep_{lca}\le deep_u\),即 \(lca\) 在 \(u\) 上方,因此我们从上往下 dfs 的时候可以访问过之前所有被挂在祖先上的可能合法的路径。
经过刻画发现这些路径的一端点一定处在「\(u\) 的抛去 \(v\) 的子树内」,不难发现这是两段 dfn 区间的交并,是可以直接维护的。因此我们只需要单点改区间查。可以做到 \(O(n\log n)\)。
P5556 圣剑护符
将问题刻画为将路径中所有数依次插入线性基,看是否存在插入失败的点。不难发现由于线性基中至多插 \(\log\) 个数,所以可以特判一下路径长度,只做长度 \(\le \log\) 的部分。
P11527 [THUPC 2025 初赛] waht 先生的法阵
不难,但是写起来比较恶心的题。
首先我们观察到这个 \(i+\gcd(i,a_i)\) 很难直接维护,考虑分块。类比弹飞绵羊一题的思路,我们令 \(pos_i\) 代表从 \(i\) 开始跳,跳出 \(i\) 所在块外的第一个点;令 \(sum_i\) 代表此时的代价。我们可以在 \(O(B)\) 的复杂度内重构一个块,求出该块中所有元素的 \(pos_i,sum_i\)。但是由于每次修改需要对 \(O(\frac{n}{B})\) 个块进行重构,所以复杂度不对。
对于一个位置 \(i\),不难发现由于区间乘会使 \(a_i\) 不降,因此当某个时刻 \(g_i=i\) 时,此时 \(\gcd(i,a_i)=i\),后续时刻这个 \(g\) 就不会在变化了,就可以根据上文提到的方法打 tag 了。可以证明总修改量是 \(O(n\ln \ln n)\) 的。对于每个质数,我们开一个二元组 set,存储所有对于该位置、乘上这个质数是「有效操作」的位置以及还可以乘这个质数作为「有效操作」的次数。对于一次询问,我们先做一个正常的分块,即对散块的处理、整块的打 tag,把 \(a_i\) 处理好。然后考虑更新所有需要更新的 \(g_i\)。将 \(c\) 质因数分解,对于一个质因数 \(p\),我们考虑直接暴力枚举 \(s_p\) 中二元组第一维在 \([l,r]\) 之间的所有位置,对 \(g\) 进行更新,并存下这些位置所对应的所有块。最后我们对这些所有块都进行 \(O(B)\) 的重构即可。不难注意到最小值取在 \(B=\sqrt \frac{q}{\ln \ln n}\),有最终复杂度 \(O(n\sqrt {q\ln \ln n})\)。
P4482 [BJWC2018] Border 的四种求法
找出最大的 \(x\),满足 \(l\le x\le r-1\) 且 \(\operatorname{lcs}(x,r)\ge x-l+1\),则答案就是 \(x-l+1\)。令 \(u_x\) 代表前缀 \(x\) 所对应的状态在树中的结点编号,即 \(\operatorname{lcs}(x,r)=len(lca(u_x,u_r))\)。给树设边权。令树边 \((\operatorname{link}(u),u)\) 的边权为 \(len(u)-len(\operatorname{link}(u))\),则不难发现 \(len(lca(u_x,u_r))=dis(lca(u_x,u_r))\),可以将式子写成 \(dis(u_x)+dis(u_r)-dis(u_x,u_r)\ge 2(x-l+1)\)。
考虑点分治。令当前分治中心为 \(p\),我们处理所有 \((u_x,u_r)\) 经过 \(p\) 的路径,此时式子左边变成 \(dis(u_x)+dis(u_r)-dis(p,u_x)-dis(p,u_r)\)。可以进行一些移项,最终我们得到了两条不等式限制。这是一个很对味的 3-side 二维数点,将第二个式子两侧的值加上偏移量后离线扫描线,zkw 线段树维护第一个式子那维的区间最大值即可。
CF2101E Kia Bakes a Cake
由于每次路径边长翻倍,因此不难发现答案不会超过 \(\log n\)。考虑对其进行 dp 转移,一个朴素的想法是,令 \(f_{i,j,k}\) 代表起点为 \(i\),当前到了点 \(j\),共经过了 \(k\) 个点,路径最后一条边的最小长度。但是这样的话我们要记起点,状态过于冗余。这个时候我们可以倒着做,令路径边长不断减半,我们更改状态的定义,\(f_{i,j}\) 代表倒着做到了点 \(i\),当前是路径的倒数第 \(j\) 个点,路径最新一条边的最大长度。这样我们就不需要记起点了,答案就是最大的 \(j\) 使得 \(f_{i,j}\) 不为零。
考虑如何转移 \(f_{i,j}\),我们可以直接枚举 \(i\) 的出边 \((i,k)\),这条边的条件即为其长度 \(\le \frac{f_{k,j-1}}{2}\),此时一定存在减半的方案,因此转移可以写成 \(f_{i,j}=\max\limits_{2dist(i,k)\le f_{k,j-1}}dist(i,k)\) 的形式。直接暴力转移复杂度不对,看到路径长度一类的最值或计数转移可以想到点分治。我们钦定当前分治重心 \(p\) 作为 \(\operatorname{lca}\),有 \(f_{i,j}=\max\limits_{f_{k,j-1}-2dis(k)\ge 2dis(i)}dis(i)+dis(k)\),其中 \(dis(i)\) 为 \(i\) 到分治中心 \(p\) 的距离。这个可以直接 BIT 解决。因此我们正反各扫一遍就可以做到不漏的对 \(f\) 取最值。由于对于每个 \(j\) 我们都需要做一次分治中心内部 \(\log\) 的 BIT 查询,因此总复杂度是 \(n\log^3 n\) 的,可过。
P9058 [Ynoi2004] rpmtdq
树上支配对模板。先把 \(dis\) 拆开,对 \(\operatorname{lca}\) 下手。点分治时钦定分治中心为 \(\operatorname{lca}\),我们发现其实有很多子树内的点对是无用的,具体来说,我们只需要保留形如 \(\max(dis_{l},dis_{r})\le \min\limits_{i=l+1}^rdis_i\) 的点对 \((l,r)\)。可以在分治中心子树内预处理出 \(dis\) 后按编号顺序将子树内的所有点插入 \(dis\) 单调不降的单调栈中,并保留每次插入后栈顶和当前点形成的点对,即保留每次插入后 \(dis\) 的前驱后继,注意到我们需要正反各插一遍。当然直接插会算重一些在同一子树内 \(\operatorname{lca}\) 不为分治中心的点对,但由于这样只会使答案更劣所以不影响正确性。
将所有有效点对保留后,直接对其做类二维数点即可,BIT 维护后缀 \(\max\)。分析复杂度,不难发现每个点在包含它的分治中心中只会贡献 \(O(1)\) 个点对,因此总共有 \(O(n\log n)\) 个点对,因此总复杂度为 \(O(n\log^2n+q\log n)\)。
CF383E Vowels
按字符集状压,于是一个状态的答案刻画为与其有交的个数。考虑减去无交的个数,不难发现等价于一个是另一个超集的子集,可以直接高维前缀和了。高维前缀和的本质是,将子集和看成有 \(n\) 维的每维值域大小 \([0,1]\) 的前缀和,跑 \(n\) 遍前缀和即可,每一遍要跑状态数个,故复杂度 \(O(n2^n)\),这比直接 \(O(3^n)\) 不知道优到哪里去了。
P6619 [省选联考 2020 A/B 卷] 冰火战士
Key Observation:每次战斗两边消耗的能量一样,因此易证最终消耗能量为 \(2\times \min(\sum\limits_{i\in \operatorname{Ice},x_i\le t}y_i,\sum\limits_{i\in \operatorname{Fire},x_i\ge t}y_i)\),其中 \(t\) 是我们钦定的温度。
令 \(I_i\) 代表温度小于等于 \(i\) 的冰战士能力之和,\(F_i\) 代表温度大于等于 \(i\) 的火战士能力之和,于是可以将上式转换为 \(2\times \min(I_i,F_i)\)。显然 \(I\) 不降,\(F\) 不升,所以函数 \(\min(I_i,F_i)\) 是具有单调性的,因此可以考虑二分或三分从而得到温度位置。注意到函数可能存在平台且不一定连续,考虑二分。
我们需要二分出两个位置,一个是最大的满足 \(I_i<F_i\) 的位置,令其为 \(pos_1\);此时所有 \(\ge pos_1+1\) 的位置都满足 \(I_i\ge F_i\),于是另一个位置是最大的满足 \(F_j=F_{pos_1+1}\) 的位置,令其为 \(pos_2\)。根据函数的单调性,显然最值只会在这两处取到。
考虑如何维护 \(I_i,F_i\)。首先先对温度离散化,由于每次的修改等价于前后缀加,查询等价于单点查,因此可以使用两个 BIT 维护。此时复杂度为 \(O(q\log^2 n)\),无法通过。考虑替换为线段树后用线段树二分优化,将 \(F_i\) 差分后的的后缀和查询转换为总和减去前缀和,这样递归左右儿子的时候就可以维护两个前缀和,直接在线段树上二分即可。此时复杂度为 \(O(q\log n)\),但是由于常数大所以无法通过。
考虑在常数更小的 BIT 上实现线段树「二分」的功能。BIT 的本质是维护 \(i-\operatorname{lowbit}+1\) 到 \(i\) 的区间和,因此我们可以倍增的向右扩展,同时维护两个前缀和,扩展的时候直接加上这个点 BIT 的贡献即可。具体来说,我们从 \(p=0\) 开始向右尝试扩展,维护当前的 \(I_p,F_p\),从高位向低位倍增,考虑能否扩展到 \(p+2^i\),此时需要加上 \([p+1,p+2^i]\) 的贡献,按理来说需要 \(O(\log)\) 的做一遍区间和,但实际上不需要,我们只需要加入 \(p+2^i\) 这个点所对应 BIT 上的值即可。这是因为倍增的时候是从高位向低位扩展的,此时第 \(i-1\) 位往下全是 \(0\),因此第 \(i\) 位就是 \(p+2^i\) 的 \(\operatorname{lowbit}\),符合 BIT 维护的定义。
一个细节是,因为 \(I_i,F_i\) 是同时扩展的,而我们在计算实际的 \(F_i\) 时需要用总和减去 \(i-1\) 位置的前缀和,而 \(i-1\) 这个位置不具有和 \(i\) 一样良好的 \(\operatorname{lowbit}\) 性质。为了避免这一点,我们需要在单点修改 \(F\) 的时候,将所有的 \(x\) 整体加一,这样总和减去 \(i-1\) 位置的前缀和实际上代表的是 \(F_{i-1}\),而非 \(F_i\)。

浙公网安备 33010602011771号