3 月做题记录
P6292
考虑建出 SAM 后扫描线。
考虑目前一个等价类集合长度区间为 \([l,r]\),显然我们扫到每个位置的时候只需要维护每个等价类的 \(\operatorname{Endpos}\) 集合中最靠右的位置。我们考虑右端点增加 \(1\) 的时候,会被修改的等价类为目前前缀对应的等价类 Fail 树上到根的路径。对于一个 \(l,r,x\),其中 \([l,r]\) 为长度区间,\(x\) 为 \(\operatorname{Endpos}\) 等价类最大值,则对于询问的左区间来说,答案构成分段一次函数。最终每个左区间答案都是关于左区间线性的,维护两个树状数组分别是斜率和截距即可。到根链覆盖直接树剖后 ODT 即可,复杂度 \(O(n \log^2 n)\)。
P11830
考虑怎么判定 \(x\) 是否可以成为中位数。
对于 \(l_{i,2}\leq x\leq r_{i,2}\) 的 \(i\),显然会取 \(r_{i,1}\) 个 \(x\),否则所有 \(r_{i,2} < x\) 的 \(i\) 都本质相同,\(l_{i,2} > x\) 的 \(i\) 也相同,于是可以得到两个区间分别表示 \(<x\) 和 \(>x\) 的数的个数在这个范围内,对这个东西解方程就能求出对应范围了。
值域很大,离散化后每段本质相同,双指针后判断即可。复杂度 \(O(n \log n)\)。
P11831
考虑时间轴分块,每 \(B_1\) 次操作重构一次。重构时对 \(a\) 的值域分块,每一块长度为 \(B_2\),每块跑一次拓扑排序 DP 即可。注意将操作所在的块内修改的点忽略,查询时对这些点重新计算。于是需要预处理一个可达关系,使用 bitset 即可。
取 \(B_1=B_2=n^{\frac{2}{3}}\) 可以得到 \(O(n^{\frac{5}{3}}+\frac{n^2}{w})\) 的做法,但是场上块长调的不太对,实现常数比较大,只能过 \(6 \times 10^4\)。
P11833
不难注意到按照 \(t\) 小到大排序后依次满足每个限制即可,模拟容易做到 \(O(n^2 \log V)\)。
注意到我们要做的就是,找到一个位置,然后将一段区间覆盖为等差数列,这个东西很容易线段树维护区间覆盖等差数列区间求和,还需要一个线段树二分。复杂度 \(O(n \log n)\)。
ARC160D
考虑倒着生成序列。每次选择一个数加 \(k\),或者选择一个长度为 \(k\) 的区间加 \(1\)。
令 \(b_i\) 为 \([i,i+k-1]\) 这个区间加 \(1\) 的次数,\(c_i\) 为 \(i\) 这个位置加 \(k\) 的次数。则合法序列与 \(\sum \limits_{i=1}^n b_i+c_i = \dfrac{m}{k}\) 且 \(\forall 1 \leq i \leq n - k + 1, 0 < b_i < k\) 的序列 \(b,c\) 一一对应。
至此可以直接容斥做到 \(O(n^2)\)。
也有一种比较无脑的做法,枚举 \(\sum \limits_{i=1}^n b_i = p\),显然有 \(0 \leq x \leq (n-k+1)(k-1)\),然后相当于要计数 \(\sum \limits_{i=1}^n b_i=p\),且 \(\forall 1\leq i \leq n - k + 1, b_i < k\) 的 \(b\) 序列数量。显然答案等于 \([x^p](x^0+x^1+\cdots x^{k-1})^{n-k+1}\),多项式快速幂计算即可。
ARC146D
可以将每个条件转化成四个条件,每个条件形如 \(x,y,c,d\),表示 \(a_x \leq y \iff a_y \leq d\)。
考虑建图,\(x\) 到 \(y\) 连一条有向边,将 \(c,d\) 计入权值中。
初始取 \(a_i = 1\),每次贪心取最小的 \(a_i\) 并对邻边进行更新。注意需要进行类似当前弧优化的状物,否则一条边可能被多次更新。精细实现可以做到线性。
ARC183D
忽略每次删叶子后树有完美匹配的性质,以重心为根,答案有上界 \(\sum \limits_{i=1}^n dep_i\) 并且可以取到,因为以重心为根不存在子树大小超过一半,根据经典结论可以每次选不同子树内两个叶子删去。
对于原题,我们声称答案仍然可以取到上界。
首先,对于一棵树来说,任取一点为根,称 \(0\) 类点为子树大小为偶数的点,\(1\) 类点为子树大小为奇数的点,则其有完美匹配等价于以下三个条件:
- 总点数为偶数。
- 对于每个 \(1\) 类点,其所有儿子都是 \(0\) 类点。
- 对于每个 \(0\) 类点,其恰有一个儿子是 \(1\) 类点。
忽略第一个限制,可以发现删除叶子 \(x\) 后,后两个限制仍然满足的充要条件是 \(x\) 到根颜色是交替的。
对于重心的每个子树,可以 DFS 求出一个删叶子顺序,重心必然在任意时刻都恰有一个儿子子树大小是奇数,其他是偶数,在偶数中选子树大小最大的点和这个奇子树配对并更新子树大小即可。
ARC153D
考虑 \(f(a+b)\),显然等于 \(f(a)+f(b)-9\times g(a, b)\),\(g(a,b)\) 表示 \(a+b\) 的进位次数。
然后考虑数位 DP,对于从右到左第 \(i\) 位,显然其右侧加上 \(x\) 会进位的数必然是只保留后面的数后排序后的一段后缀。于是记 \(f_{i,j}\) 表示到第 \(i\) 位,第 \(i-1\) 位也就是右侧的那位会进位的最小的是第 \(j\) 个数。转移可以顺序枚举 \(j\),注意到 \(j \gets j+1\) 时只需要在一个集合中加入或删除一个数,查询是查询最小值。set 访问首迭代器的复杂度是 \(O(1)\) 的,所以复杂度是正确的。
ARC185D
考虑只有一条链怎么做。这是很经典的,记 \(f_i\) 表示点 \(i-1\) 到 \(i\) 的期望步数,不难发现 \(f\) 是差为 \(2\) 的等差数列,直接简单求和即可。
对于若干条链来说,先考虑两条链怎么做,考虑将过程分为到达某个链底端,然后走到另一个链底端。第二部分就等价于一条链从左走到右,第一部分等价于只有一条链,因为每次往上和往下都可以对应成一条链的情况。
对于更多的链,考虑仍然将过程分段,依次是到达每条链的底端。根据期望的线性性将每段答案求和即为最终期望。
第一次到达链底相当于就是只有一条链,而后面的每次等价于事实上只有两条链,但是到根后往已经走过的链和未走过的链的概率不同,这个东西和一条链上的部分一样,只需要把根往下的答案重算一下即可。复杂度 \(O(n \log mod)\)。
ARC176D
考虑 \(\sum \limits_{i=1}^{n-1} |p_i - p_{i+1}|\),拆贡献可以变为 \(\sum \limits_{i=1}^n \sum \limits_{j=1}^{n-1} [[p_j \geq i] \neq [p_{j+1} \geq i]]\)。
枚举 \(i\),则序列变为 \(01\) 序列。显然本质不同的 \(j\) 只需要考虑 \((p_j,p_{j+1})\) 现在是多少,所以本质只有 \(4\) 种。
考虑矩阵,对这些东西的贡献转移写成矩阵形式即可。
P6976
考虑分治,每次在当前多边形内选一条边把多边形断开,将两边的询问递归,跨过边的询问直接从选择的边的端点开始 BFS。
考虑复杂度,可以证明必然存在一条边使得较小侧点数至少为 \(\dfrac{1}{3}\) 的总点数。所以总复杂度为 \(O(n \log n)\)。
BZOJ3591
加强版:\(n \leq 20\)。
原题是,考虑一般的 DP 套 DP,考虑用那个维护单调序列的做法维护 LIS,那么每个数只有三种状态:不在序列中,在序列中但不在队列中,在队列中。用一个三进制状态即可做到 \(O(3^nn)\)。
这个做法太菜了,考虑按照值域插入所有数,我们只需要记录 \(f_i\) 表示 \([1,i]\) 的 LIS,显然有 \(f_i-f_{i-1}\in\{0,1\}\),所以状态是 \(O(2^n)\) 的。
要求给定序列在排列中,考虑记 \(g_{i,j,S}\) 表示插入了 \([1,i]\),目前 \(f\) 状态为 \(S\),目前在给定序列中出现过的位置最大的在 \(j\)。注意到 \(S \leq 2^i\),状态数是 \(O(n2^n)\) 的,转移可以做到 \(O(n)\),总复杂度 \(O(n^22^n)\)。
CF1142D
考虑对于符合条件的数 \(x\),排名为 \(k\),\(10x\) 的排名是多少。
观察规律能看出 \(10x\) 的排名只和 \(k \bmod 11\) 有关,对 \(k \in [0,10]\) 打个表出来即可。
然后直接 DP,\(f_{i,j}\) 表示以 \(i\) 结尾,排名模 \(11\) 余 \(j\) 的符合条件的数的个数,转移很容易。
CF995F
\(D \leq n\) 时可以直接 \(O(n^2)\) DP 计算答案。
比较容易猜出答案关于 \(D\) 是一个多项式,对 \(ans_1,ans_2,\cdots,ans_n\) 拉插即可。
另一个做法是,考虑记 \(g_i\) 表示填入的数有本质不同的 \(i\) 个,且每个数在 \([1,i]\) 范围内的方案数。则答案等于 \(\sum \limits_{i=1}^n \dbinom{D}{i} g_i\)。
考虑 \(g_i\) 怎么求。考虑之前的 DP,\(f_{i,j}\) 表示以 \(i\) 为根的子树,点 \(i\) 填了 \(j\)。\(g_i\) 不等于 \(f_{1,i}\),因为 \(f_{1,i}\) 可能并没有完全包含 \([1,i]\) 中所有数。枚举有 \(j<i\) 种不同的数可得 \(g_i = f_{1,i} - \sum \limits_{j=1}^{i-1} \dbinom{i-1}{j-1} g_j\),直接计算即可,复杂度 \(O(n^2)\)。
CF1499G
好题啊。
先考虑无修改。
这是一个比较经典的问题:给定一个二分图,选一些边,使得每个点的选与没选的邻边数差的绝对值总和尽可能小。
对于这个问题,从所有点度数为偶数下手,此时图存在欧拉回路,求出一条欧拉回路后考虑每条被定向的边 \(u \rightarrow v\),若 \(v\) 是黑色点则选这条边否则不选。此时对于每个点,要么所有出边都被选,要么所有入边都被选,所以每个点的答案都为 \(0\),总和也为 \(0\),取到最小值。
有些点度数为奇数时,答案下界为 \(\sum \limits_{i=1}^n [2 \nmid deg_i]\)。这个下界是可以取到的。建立虚点向所有度数为奇数的点连边,这个图有欧拉回路,求出欧拉回路后对所有原图上的边按照同样方式定向即可。
考虑原题,现在要在线加边,维护欧拉回路。问题是由于虚点存在,可能还有删边,不容易做。
考虑这个东西的本质,事实上我们可以证明我们只需要求出以下问题的解即可还原答案:
将二分图的边划分为若干环和路径,路径不要求简单,使得每个点至多成为一条路径的端点。
对于环和路径,都是交替地取边,这一定可以得到最小答案,原因是考虑度数为偶数的点无论如何都只会在环上或者路径的非端点处,所以贡献为 \(0\)。度数为奇数的点必然恰好成为一条路径的端点,贡献为 \(1\),正好符合静态的做法。
剩下的过程就很容易了。考虑在路径端点维护对应路径,每条路径只在其一个端点维护。则加入一条边时,分类讨论:
- 两端都不为路径端点,直接加入这条边作为路径。
- 有且仅有一端为路径端点,将路径加上这条边扩展为新路径。
- 两段都为路径端点且属于同一路径,加入这条边后成为环,将环上边删去并加入到答案即可。
- 两段都为路径端点且不属于同一路径,合并两条路径。
使用 deque 可以很好地支持这个操作,注意到复杂度瓶颈在于最后一种情况的合并路径,于是启发式合并即可。复杂度 \(O(n \log n)\)。
CF1149E
对于每个点 \(u\) 考虑其类 SG 函数 \(f(u) = \operatorname{mex} \limits_{(u,v) \in E} f_v\)。
定义 \(g(u) = \bigoplus \limits_{f(x) = u} h_x\)。我们声称先手必胜当且仅当 \(\sum g_u > 0\)。
证明:
- 终止状态必然满足 \(\forall 1 \leq i \leq n, h_i = 0\),则有 \(\sum g_u = 0\)。
- 对于 \(\sum g_u = 0\) 的局面,考虑操作任意一个点 \(v\),那么 \(h_v\) 减少,必然有 \(g(f_v) \neq 0\),并且由于 \(f\) 为一步到达的点的 \(f\) 的 \(\operatorname{mex}\),于是 \(g(f_v)\) 不可能通过修改其他点进行更改,于是 \(g(f_v) > 0\),\(\sum g_u > 0\)。
- 对于 \(\sum g_u > 0\) 的点,找到最大的 \(x\) 使得 \(g_x > 0\),考虑 \(g_x\) 是若干数的异或,根据 nim 游戏的结论总能减少某个 \(f_v = x\) 的 \(h_v\) 使得 \(g_x = 0\)。同时,\(v\) 的所有一步到达的点都能被任意修改,所以总存在方案使得操作后 \(\sum g_u = 0\)。
- 局面构成的博弈是有向无环图。考虑若存在某个局面在至少一次操作后回到了这个局面,则考虑最后一次操作的 \(u\) 必然在之前的操作中成为过被修改的后继,对那个点重复论证即可得到原图有环,与题意矛盾。
如果能看懂证明的话构造方案是容易的。
CF1830F
考虑朴素 DP,记 \(f_i\) 为 \([1,i]\) 中最后选了的点为 \(i\),但以 \(i\) 为最右被选区间的贡献还未加入时的最大答案。有转移 \(f_i = \max \limits_{1 \leq j < i} \{f_j + p_j \times c(j,i)\}\),\(c(j,i)\) 是有多少区间包含 \(j\) 但不包含 \(i\)。
在枚举 \(i\) 从 \(1\) 到 \(n\) 的过程中进行扫描线,则变为了区间 \(c\) 加 \(1\),区间查询 \(\max\)。KTT 维护即可。
CF1158E
对于猜树的形态,经常考虑的做法是以某个点为根后依次确定每个点的深度和父亲。
假设树以 \(1\) 为根,问题分为两部分:
-
确定每个点的深度。
注意到我们将 \(d_1\) 设为 \(k\) 和 \(k-1\) 进行两次询问就能求出所有深度为 \(k+1\) 的点,并且能分出深度 \(<k+1\) 的和深度 \(>k+1\) 的点。
进行类似分治的过程,初始时求出深度为 \(mid = \lfloor \dfrac{n+2}{2} \rfloor\) 的深度的点,然后可以发现每一步我们得到了形如若干 \((l,r,S)\) 的区间,表示深度在区间 \([l,r]\) 内的点恰好是集合 \(S\),并且可以发现深度为 \(l-1\) 的所有点必然已经被求出。那么将深度为 \(l-1\) 的点的 \(d\) 设为 \(mid-l+1\) 和 \(mid-l\) 就可以将区间划分为 \([l,mid),[mid,mid],(mid,r]\)。
考虑将过程并行维护,但是发现下一个区间可能会通过父亲的若干条边影响之前的区间,但是这个过程是分治执行的,所以把奇数编号的区间拉出来并行,偶数拉出来并行,两两之间不会影响。
上述的询问次数是 \(4\log n\)。
-
确定每个点的父亲。
对于深度为 \(x\) 的点,依次考虑二进制下每一位 \(y\),将这些点中编号这一位是 \(1\) 的点的 \(d\) 设为 \(1\),则深度为 \(x+1\) 的点的父亲这一位是 \(1\) 当且仅当回答的结果为 \(1\)。于是将所有回答结果加权求和即可得到 \(x+1\) 层每个点的父亲。
这个过程可以模 \(3\) 分组并行,询问次数 \(3 \log n\)。
总询问次数 \(7 \log n\),可以通过。
P11832
对于图是树的时候,以 \(1\) 为根,递归儿子对应子树随意排列,将这个点本身随意插入到两个空位之间。
图不是树时,发现环的构造情况较少,具体地只要确定了在序列中出现的最靠前的位置,其他点要么顺时针排列要么逆时针排列,所以事实上环上的点在序列中顺序必然是某个顺时针或逆时针顺序。
注意到同胚于 \(\operatorname{K4}\) 的子图无解,杏仁图也无解,所以原图是广义串并联图,每个点双是外面一个哈密顿回路和中间的若干条不交的边构成的平面图。
建圆方树,发现对于圆点来说,结论和树上一样,递归到子树构造并随意排列后插入,对于方点限制有所不同,儿子节点必须按照哈密顿回路上的顺序,也就是只有两种需要考虑的顺序,贪心取较小的即可。
所以只需要求一个这样的点双的哈密顿回路即可,直接按照广义串并联图的套路即可,不过这题不需要缩一度点,因为任意时刻都不会有叶子,所以只需要缩二度点与叠合重边,叠合重边时将原有边覆盖即可。
图不连通时先求出每个连通分量的序列答案,注意到我们只需要求任意两个联通分量序列上要么不交要么包含,排序后可以贪心构造答案。
CF1147F
无边权限制时,后手必胜当且仅当图的所有最大匹配都包含起点。但是图是完全二分图,所以后手必胜。
有限制时,后手仍然必胜,只需要找到一个稳定婚姻系统即可。
CF1400F
注意到本质就是给定若干字符串,要求删若干字符使得这个串中不出现给定串,对给定串建 ACAM 然后 DP 即可解决问题。
进一步注意到合法字符串数量很小,当 \(x=19\) 时数量取到最大值为 \(2399\),所以直接做就是对的。
ARC179D
当根固定时,我们希望一个一个子树走,记 \(f_{i,0/1,0/1}\) 表示从点 \(i\) 出发遍历子树内所有点,要求能否用门,要求是否需要回到 \(i\) 的答案。转移是很容易的,于是 \(O(n^2)\) 是很显然的。
这个 DP 很容易做换根,做完了。
P4119
离散化对值域分块,常见做法是先求出答案在哪一块,然后对这一块内每个点求区间内出现次数。后面的部分,区间内出现次数可以分块维护。前面的部分,对每一个值域内的块在原序列上也分块,维护每个块和之前的出现次数总和,每一块再维护一个并查集就可以了。
ARC150D
限制只随机到某些点不好处理,假设会随机选到所有点,但是选到那些点时不计算贡献即可。
根据期望线性性,只需要对于每个 \(i\) 求 \(E(x_i)\),\(x_i\) 表示操作过程中点 \(i\) 被选到的次数。
对于每个点 \(i\),只保留从根到 \(i\) 的点的这条链计算答案就是对的,原因是考虑当且仅当点 \(i\) 到根都被选后这个点不再有贡献,所以可以假设每次选的点都是在这条链上的,其他情况不影响答案。
考虑这条链的答案,则初始时没有好的点,假设点 \(i\) 深度为 \(d\),容易推出式子是关于 \(d\) 的一个调和级数的形式,直接计算并对所有点求和即可。
CF1031E
限制很紧,肯定是希望每次至少能删 \(3\) 个 \(1\),最后剩下的 \(12\) 可以爆搜调整。
\(3\) 个一组不能一次删完,但是暴搜可以发现每 \(6\) 个一组在忽略后面的数时可以 \(2\) 次删完,于是前面分组做最后剩下若干个爆搜即可。
CF776G
显然 \(x \oplus y<x\) 等价于 \(y\) 的最靠左的 \(1\) 的位在 \(x\) 中也为 \(1\)。
枚举 \(k\) 为 \(x\) 在 \(16\) 进制表达下的最大数码,则可以直接从后往前做数位 DP,记 \(f_{i,0/1,0/1}\) 表示到了第 \(i\) 位,是否有最高位顶满的限制,后面是否存在某一位为 \(k\),复杂度 \(O(q \log^3 V)\)。
CF1535F
忽略不能转化的条件,则答案至多为 \(2\),只需要考虑哪些对 \((i,j)\) 的答案为 \(1\)。
\((i,j)\) 答案为 \(1\) 当且仅当删除 LCP 和 LCS 后有一个串是有序的。
枚举其中有序的那个串,比如是 \(s_i\),将 \(s_i\) 划分为若干极长连续排序段,只需要对每段算贡献。容易发现每对 \((i,j)\) 有且仅有一段会进行贡献。
建出正串和反串的字典树就变成两棵树的两个子树交,由于权值是排列所以是二维数点问题,扫描线即可。
数论题
考虑什么样的 \(d,g\) 会真正的产生贡献而不是相互抵消。
可以发现很多时候 \(g_i = 0 / 1\) 会将贡献抵消,将 \(\gcd(s,n)\) 分解质因数,记其为 \(p_1^{k_1}p_2^{k_2}\cdots p_{x}^{k_m}\)。则只有 \(d_i = k_i\) 且 \(g_i = 1\) 或 \(d_i = g_i = 0\) 贡献才不会抵消。
对这些特定的 \(d,g\) 计算答案,复杂度 \(O(2^{\omega(n)})\)。
CF2068K
考虑一个暴力的模型:首先将 \(a_i\) 相等的点缩一起,假设有 \(q_i\) 个 \(a=p_i\),连边 \(S \rightarrow i\),容量为 \(q_i\)。另外,对于每个时刻 \(i > 0\),建立点 \(t_i\),对于所有 \(p_j \mid i\),连边 \(j \rightarrow t_i\),容量为 \(1\),另外连边 \(t_i \rightarrow T\),容量为 \(1\)。可以发现在 \(i\) 时刻内有解当且仅当只保留 \(t_1,t_2,\cdots,t_i\) 这些点和对应的边后最大流为 \(n\)。
直接加虚点的复杂度和答案大小有关,无法通过。
注意到我们可以只建立部分虚点,具体地,每次取最小的需要建立虚点的时刻 \(i\),加入点 \(t_i\) 后判断最大流是否增加。若增加,将 \(i + p_j\) 也设为需要建立虚点的时刻,其中 \(p_j \mid i\)。不难证明这样做的正确性。
可以证明复杂度为 \(O(n^2\log n)\)。
CF2068H
把这个相邻两项曼哈顿距离补全成环,记 \(d_0 = \operatorname{distance}((0,0),(x_n,y_n))\)。
不难发现有解的两个必要条件:
- \(a+b\) 与 \(\sum \limits_{i=1}^{n-1} d_i\) 同奇偶,即 \(\sum \limits_{i=0}^{n-1} d_i\) 为偶数。
- \(a+b \leq \sum \limits_{i=1}^{n-1} d_i\)。即 \(d_0 \leq \sum \limits_{i=1}^{n-1} d_i\)。进一步地,对于所有 \(i\) 都有 \(d_i \leq \sum \limits_{j \neq i} d_j\),意义是直接走的距离总是不超过绕一圈的距离。
事实上这是充要条件。考虑给出归纳性证明。
对于目前的终点 \((a,b)\),我们只需要找到 \((x_{n-1},y_{n-1})\) 使得新的 \(d_{0}',d_1,\cdots,d_{n-2}\) 符合上述两个要求。
考虑条件 \(1\),发现无论如何选择 \((x_{n-1},y_{n-1})\) 总天然满足限制,原因是绕一圈必然有总距离为偶数。
对于条件 \(2\),先考虑 \(d_{0}' \in [|d_0 - d_{n-1}|,d_0+d_{n-1}]\),并且 \(d_0'\) 能取到范围内与 \(d_0 + d_{n-1}\) 同奇偶的所有值。这个是由于 \((x_{n-1},y_{n-1})\) 总在 \((x_n,y_n)\) 为中心的一个斜三角形边上。
事实上我们可以证明取 \(d_0' = \min(d_0+d_{n-1},\sum \limits_{i=1}^{n-2} d_i)\) 符合归纳条件。这个可以分类讨论 \(\min\) 取在哪一边。
\(n\) 很小,咋维护都行。
P6109
如果查询的矩阵满足 \(l_1 = 1\),则可以从上往下扫描线维护区间加区间历史最大值。
\(r_1=n\) 也可以这么做。也就是说如果询问的矩形上边界或下边界正好是矩形边界就容易维护了。
考虑形如这种如果在边上就容易做但是区间不容易维护的问题,考虑猫树分治。即对于目前递归区间 \([l,r]\),考虑所有跨过 \(mid\) 的区间的询问,例如 \([l',r']\) 使得 \(l \leq l' \leq mid < r' \leq r\),则将询问挂在 \(l'\) 和 \(r'\) 处,发现只需要维护一棵线段树支持区间加区间历史最大值,另外能维护将整棵树每个节点的历史最大值还原成区间最大值的操作即可。
总复杂度 \(O(n \log^2 n+q \log n)\)。
CF1566G
看着就是怎么分讨一下。
大多数情况下你肯定希望选两条最小的边,但是这样的边可能有公共端点。
考虑记边权最小的边的端点为 \((u,v)\),考虑两种选择方式:
-
不存在选择的某个点对为 \((u,v)\),此时可以发现如果这是最优解,则必然选取的两个点对为 \((u,a)\) 和 \((v,b)\)。
则要么是 \((u,a)\) 和 \((v,b)\) 均为边,要么形如 \((u,a)\) 是边但 \((v,b)\) 不是,此时必然可以调整使得答案不劣。所以只有可能 \((u,a)\) 和 \((v,b)\) 都是边。
-
存在选择的某个点对为 \((u,v)\)。此时要么选择另一条边 \((u',v')\) 使得顶点没有重复,要么形如选择 \(u\) 的两个邻居 \((a,b)\)。
于是只需要考虑三种情况,分别是选择 \((u,v)\) 和另一条边,选择 \((u,a)\) 和 \((v,b)\) 两条边,或者选择 \((a,b)\) 和 \((u,v)\) 且 \(a,b\) 是 \(u\) 或 \(v\) 的邻居。
后两种比较容易,第三种直接维护,第二种注意到只需要对于每个点存前三小条边即可,对于第一个来说,考虑选择的另一条边必然是在两端排名都不超过三的,于是直接维护即可。
CF1919E
考虑将 \(s_0 = 0\) 也加入,则变为求 \(p\) 有多少排列使得 \(p_1 = 0\),且对于所有 \(1 \leq i \leq n\) 有 \(|p_i - p_{i+1}| = 1\) 的排列 \(p\) 数量。
考虑到 \(0\) 比较特殊,将 \(0\) 的位置切开后每一段区间都是全负数或者全正数,于是考虑对负数和正数分别 DP。
以正数为例,注意到如果我们对值域从大到小插入,则每次我们增加的新数 \(x\) 左侧和右侧必然要么为空要么为 \(x-1\)。
于是考虑连续段 DP,记 \(f_{i,j,0/1}\) 表示插入了 \(\geq i\) 的所有数,现在构成了 \(j\) 个连续段,是否存在某个连续段已经选择了 \(n\) 这个点的方案数。注意到这 \(j\) 个连续段每个连续段要么左右都是 \(i\),要么就是序列的后缀,也就是 \(n\) 在这个区间最右侧。
注意到如果现在有 \(j\) 个连续段,插入 \(c\) 个相同的数后连续段数量要么是 \(c-j\) 要么是 \(c-j+1\),这个值是与状态中最后的 \(0/1\) 有关的,转移过程的系数是一个插板法就可以解决的东西,正负数的合并直接枚举正数的连续段数量即可。
P4633
多边形互不相交,求深度,很显然地预示着扫描线。
每个多边形可以拆成若干个矩形,显然只对矩形做答案不会发生变化,于是考虑所有多边形都是矩形的情况。
对于每个矩形求出其右边距离最近的矩形,则这个矩形的父亲要么是那个矩形,要么这个矩形和那个矩形是兄弟关系,具体地这是取决于这两个矩形的包含关系。扫描线的时候维护区间覆盖即可。
CF1687D
注意到满足 \(x-g(x) < f(x)-x\) 的 \(x\) 为 \(1,2,4,5,6,9,10,11,12,\cdots\),在数轴上来看,构成了长度为 \(2,3,4,\cdots\) 的连续段,且段之间是长度为 \(1,2,3,\cdots\) 的连续段。第 \(i\) 个可行连续段的起点为 \(i^2\),长度为 \(i+1\)
。
考虑枚举 \(a_1 + k\) 在第 \(i\) 段开头,注意到 \(i=a_n\) 则一定符合条件,所以 \(i \leq a_n\)。
\(a_1+k\) 在开头时取值为 \(k\),\(k'\) 是我们真正需要的答案。此时可以对 \(k'\) 求出一个范围,但是同时对于后面的每一段,\(a_i + k\) 若在可行段内,则 \(a_i + k'\) 不能进入下一段,同时 \(a_i + k\) 若不在可行段内则 \(a_i + k'\) 必然恰好切换一段。
注意到每次往后枚举段的复杂度为 \(O(\dfrac{V}{i})\),所以总复杂度是调和级数的。
CF1718D
显然的观察是,两个序列相似等价于大根笛卡尔树相同。
对排列 \(p\) 建大根笛卡尔树,对于其上的每个 \(a_i = 0\) 的点可以通过子树和祖先算出一个区间 \([l_i,r_i]\),表示最终序列 \(a_i \in [l_i,r_i]\)。
考虑如果最终求出了一种方案使得对于所有 \(i\) 有 \(a_i \in [l_i,r_i]\),则必然存在方案使得笛卡尔树相同,原因是可以发现如果有两个点 \(i,j\) 不满足笛卡尔树偏序关系的话可以简单进行调整。
于是问题变为每次给你一个 \(x\),你需要将 \(S \cup \{x\}\) 与所有区间进行完美匹配,使得每个集合内的数被其所匹配的区间包含。
先考虑单次询问,将所有区间按照右端点排序,每次取目前 \(\geq l\) 的最小的数进行匹配即可。
考虑霍尔定理的形式可以发现,可行的 \(x\) 必然是一个区间,这个是因为霍尔定理中可以发现可行的 \(x\) 应该是若干区间的交。
如果能求出任意一个可行的 \(x\),往两边二分即可求出区间。
对初始的 \(S\) 按照这样的贪心做,发现若存在 \(x\) 条件则最后必然留下一个区间,这个区间的右端点必然是一个符合条件的 \(x\),事实上这也是符合条件的最大的 \(x\)。
直接二分,在判定时维护贪心,复杂度 \(O(n \log^2 n)\),注意到贪心过程可以并查集维护,复杂度 \(O(n \log n \alpha(n))\),可以通过。
CF1712F
多源 BFS 算出距离每个点最近的叶子距离,记为 \(g_i\)。
先考虑刻画询问 \(x\) 情况下两点之间最短距离 \(d(i,j)\)。显然路径至多经过一次新增的边,于是 \(d(i,j)=\min(dis(i,j),g_i+g_j+x)\),其中 \(dis\) 是树上路径。
发现答案不超过 \(n\),考虑初始化 \(ans \gets 0\),每次尝试增加 \(ans\),即需要判断是否存在 \(i,j\) 使得两部分都大于 \(ans\)。
枚举 \(i\),不断尝试增加 \(ans\),这个过程的势能显然是对的。现在只需要判断是否存在 \(j\) 满足 \(dis(i,j) > ans\) 且 \(g_i + g_j+x > ans\)。只考虑下面的限制,要求 \(j\) 是按照 \(g\) 排序的一段后缀,前面的限制就变为了求 \(i\) 到这段后缀中最远的点的距离。对每个后缀求一个点集直径即可。欧拉序维护 LCA,复杂度 \(O(nq + n\log n)\)。
CF1672I
看着很难做,考虑一个贪心,每次取 \(|p_i - i|\) 最小的 \(i\) 进行操作,则整个过程的 \(m\) 就是每次操作的 \(|p_i - i|\) 的最大值。
事实上这个贪心是正确的,考虑操作 \(i\) 后其他的 \(|p_j - j|\) 必然不会增大,所以如果没操作 \(i\) 可以将这两次操作交换,答案显然不会变差。
于是 \(O(n^2)\) 的模拟是简单的。现在考虑怎么优化。
注意到对 \(p_i=i\) 的 \(i\) 进行操作时,对于其他的某个 \(p_j = j\),操作后仍然满足 \(p_j = j\)。
将 \(i\) 分为 \(p_i \geq i\) 和 \(p_i < i\) 两类考虑,则除了 \(p_i < i\) 可能会变为 \(p_i = i\) 外,两类在操作过程中都不会变为另一类。
只考虑 \(p_i \geq i\) 的那些位置,考虑如果有 \(i<j\) 且 \(p_i > p_j\),则必有 \(p_j - j < p_i - i\),故 \(i\) 是没有意义的。所以对于 \(p_i \leq i\) 的位置,只有 \(p\) 的后缀最小值需要维护。同理,\(p_i < i\) 的部分只有 \(p\) 的前缀最大值需要维护。
此时之前的二维信息,由于序列有序,只需要维护线段树二分就变成了后缀修改。每次取出最小的 \(|p_i - i|\) 后删除其并线段树二分出新增的后缀最小值或前缀最大值。由于操作过程中未被删除的数相对关系不变,加入位置时维护之前修改的树状数组即可。
P11956
求出直径端点 \(u,v\),不难看出答案等于 \(\sum \limits_{i=1}^n \max(dis(u,i),dis(v,i)) - dis(u,v)\)。
动态加叶子维护这个东西有点麻烦,根据经典套路,加叶子维护直径时直接维护直径中点或中边即可。离线将树建出来,发现每次直径中点或边只会至多移动一步,分类讨论一下发现只需要维护单点修改子树求和,树状数组维护即可。
CF1630E
先计算本质不同的环数,用总连通块数除以这个值即为期望。
对本质不同序列计数很容易,考虑每个本质不同的环对应几个序列。不难发现若这个环的最小循环节为 \(x\),则对应着 \(x\) 个序列,因为你只关心这个环在循环节上的起点。
最小循环节不是很容易,考虑容斥。只需要对于每个 \(x\) 求 \(x\) 为循环节的序列数量然后容斥即可。
对于连通块总和,考虑若所有数相等,则答案为 \(1\)。否则对于一个环,连通块数即为 \(n - c\),其中 \(c\) 为相邻两个相同的边数。
和上面一样考虑对每个 \(x\) 求 \(x\) 为循环节的联通块数总和,由于每条边本质相同,于是考虑每条边的贡献,枚举 \(y\) 表示这条边相邻两个都是 \(y\) 的序列数量即可。
复杂度 \(O(nd(n))\)。
P11933
注意转折点必然是给定的点,求出两点边权后相当于是 DAG 最短路,DP 即可。
特别地你需要将每个点拆成两个状态分别表示进入这个点的直线斜率和这个点对应的那条的关系,这样才能处理穿过一个点而不是一条直线的贡献。
直接求边权是三次方的,瓶颈在于求两个点连线经过了几条线,枚举 \(i\),将所有 \(j\) 按夹角排序,类似扫描线地维护即可,可能需要树状数组或者平衡树。
P4260
首先 \(p\) 毫无意义,因为已经确定有 \(n\) 局赢了。
把获胜记为 \(+1\),失败记为 \(-1\),分数就是最大后缀和。即求所有局面的最大后缀和的和。
显然把序列翻转答案是一样的,变成最大前缀和的和。
先考虑怎么对于每次询问线性计算,枚举答案 \(k\),计算有多少局面的最大前缀和不超过 \(k\)。则等价于起点为 \((0,0)\),到达 \((m,n)\),每次向左或向上,不触碰直线 \(y=x+k+1\) 的方案数,这是经典反射容斥,答案等于 \(\dbinom{n+m}{m} - \dbinom{n+m}{m+k+1}\)。
推一下式子答案大概形如 \(\sum \limits_{k=1}^n k \times (\binom{n+m}{m+k} - \binom{n+m}{m+k+1})\),\(n>m\) 时 \(k\) 需要从 \(n-m\) 开始枚举。
这个式子进一步展开发现你只需要维护组合数前缀和,这个东西是经典莫队,直接计算即可,复杂度 \(O(n \sqrt n)\)。
CF850D
首先你需要掌握兰道定理,描述如下:
对于一个 \(n\) 个点的竞赛图,记 \(d_i\) 表示点 \(i\) 的出度,不妨设 \(d_1 \leq d_2 \leq \cdots \leq d_n\),则一个序列 \(d\) 存在符合条件的竞赛图等价于 \(\forall 1 \leq i \leq n, \sum \limits_{j=1}^i d_j \geq \dbinom{i}{2}\),且 \(i=n\) 时取等。
证明:
必要性显然,因为每个符合条件的竞赛图中选 \(i\) 个点,出度之和不小于内部的边数,即 \(\dbinom{i}{2}\)。
对于充分性,我们给出一个构造性算法。
记目标出度序列从小到大排序后为 \(a_1,a_2,\cdots,a_n\)。考虑初始图 \(G\),对于每个 \(i>j\),\(i\) 向 \(j\) 连一条有向边。则每个点的出度为 \(0,1,2,\cdots,n-1\),我们将这个序列记为 \(b_1,b_2,\cdots,b_n\)。我们需要时刻保证 \(\forall 1 \leq i \leq n, \sum \limits_{j=1}^i a_j \geq \sum \limits_{j=1}^i b_j\)。显然初始的图符合条件。 接着我们进行若干轮,每轮尝试更改图使得在保证条件成立的前提下逐步调整成目标出度序列。
具体地,每一次,先将 \(b\) 从小到大排序,然后找到最小的 \(x\) 满足 \(a_x > b_x\),找到最小的 \(y\) 满足 \(a_y < b_y\)。\(x,y\) 的存在性显然,并且必然有 \(y>x\),这是因为考虑第一个 \(a_i \neq b_i\) 的位置 \(i\),若 \(a_i > b_i\) 则 \(y>x\),否则 \(\sum \limits_{j=1}^i a_j < \sum \limits_{j=1}^i b_j\),与限制矛盾。
进一步地,必然有 \(b_y > b_x + 1\),所以必然存在一个点 \(z\) 满足目前图中有 \(y \rightarrow z\) 并且 \(z \rightarrow x\),将两条边反转,\(b_x \gets b_x + 1\),\(b_y \gets b_y - 1\)。容易看出这样操作后仍然符合 \(\forall 1 \leq i \leq n, \sum \limits_{j=1}^i a_j \geq \sum \limits_{j=1}^i b_j\)。
注意到每次操作后出度序列的曼哈顿距离恰好减 \(2\),所以有限次操作内必然会得到一个图的出度序列和目标序列相同。
证毕。
原题在知道前置结论后是很容易的,注意到答案不超过 \(61\),考虑记 \(f_{i,j,k}\) 表示用了集合从小到大排序的前 \(i\) 个数,目前点数为 \(j\),目前出度和为 \(k\) 是否可行。转移是容易的,记录转移前驱后即可还原可行的出度序列,按照上述定理的构造即可。
CF1844G
假设树以 \(1\) 为根。
考虑求出相邻两个点 \(i,i+1\) 的 LCA,记为 \(x\),记 \(dis_i\) 表示 \(i\) 到根路径权值和,则 \(dis_i+dis_{i+1}-2 \times dis_x = d_i\)。
\(dis_1 = 0\),所以能递推求出 \(dis_i\) 模 \(2\) 意义下的结果。
由于已知 \(dis_x\) 模 \(2\) 的结果,所以 \(2dis_x\) 模 \(4\) 的值唯一确定,于是又可以递推出 \(dis_i\) 模 \(4\) 的结果。
不断这样做,可以求出 \(dis_i\) 模 \(2^{62}\) 的值,此时已经得到真实值了,只需要判定真实值是否合法即可。
CF1060H
注意到 \(xy = \dfrac{(x+y)^2-x^2-y^2}{2}\)。
首先可以龟速乘算出 \(x \times y\),其中 \(x\) 是某个格子而 \(y\) 是常数。
另一方面,也可以算出 \(x-y\) 的结果,其中 \(x\) 和 \(y\) 都是格子,因为 \(x+(p-1)y \equiv x-y \pmod p\),所以先让 \(y\) 乘以 \(p-1\) 后加上 \(x\) 即可。
难的是怎么算 \(x^2\)。
\(d=2\) 时很容易,\(d>2\) 时,考虑到我们只能算 \(x^d\),所以我们希望能求出一组 \(a\) 使得 \(x^2 = \sum \limits_{i=0}^d a_i(x+i)^d\),将后面的东西二项式展开,可以列出一个线性方程组,对方程组高斯消元,打表发现 \(d \leq 10\) 时方程组必然有解,于是直接用 \(a\) 计算即可。
下面的除以 \(2\) 直接乘以 \(2\) 的逆元即可。
注意到过程中你可能还需要求出某个格子使得其值为 \(0\),也就是你需要将某个格子加上 \(p-1\),这个东西直接对 \(p-1\) 拆位做即可。
次数应该是很松的,我的实现不超过 \(3000\) 次。
P5210
记点 \(i\) 的区间为 \(S_i\)。
有一个比较烂的做法是,考虑询问区间 \([l,r]\),什么样的区间 \(S_i\) 是会被查询到的,则等价于 \(S_i \subseteq [l,r]\) 且 \(S_{fa_i} \not \subseteq [l,r]\)。
把 \(S_i\) 分为两类,分别是父亲的左端点和这个区间左端点相等,或者右端点和这个右端点相等。然后考虑扫描线,以左端点相等为例。
发现扫到 \(r\) 时,对于一个区间 \([l,r]\),在其父亲对应的 \([l,r']\) 处会被删除,我们相当于要维护动态加删点,求 \(l \geq x\) 的点到 \(u\) 的距离的和。
直接点分树统计答案,每个点可能要维护个动态开点树状数组或者平衡树之类的。复杂度是 \(O(n \log^2 n)\) 的,不知道能不能过。
上面这个做法几乎完全没用到线段树的性质,从树上考虑询问 \([l,r]\) 定位到的区间是哪些。求出 \(l-1\) 和 \(r+1\) 对应叶子结点的 LCA,则定位到的点就是两条链上的点的左或右儿子,考虑需要求的距离和在这个结构上是很容易的,求出 \(u\) 到链上最近的点,则上面和下面的两部分分开讨论即可。复杂度是 \(O(n \log n)\) 的。
CF333C
提供一个小丑做法。
看着就有一个做法是,选择一个区间放上 \(k\),前后缀填一些使得结果都为 \(0\) 或 \(1\)。
这样构造出来的数量明显不够。
聪明一点,枚举 \(k=a+b\),把 \(a,b\) 放入两个区间,分出来的三部分结果都要求为 \(0\) 或 \(1\)。
这样可能还不够,在尝试 \(k=ax+b\),或者 \(k=ax+by\),\(k=a-b\),\(k=ax-b\) 之类的,多尝试一些组合就可以构造出 \(3 \times 10^5\) 的。
代码太屎了,估计没人想看。
P11959
存在长度大于 \(1\) 的回文子串等价于存在长度为 \(2\) 或 \(3\) 的回文子串。
进一步可以看出,一个字符串 \(s\) 是动听的,等价于对于任意 \(s_i = s_j\) 且 \(i<j\),都有 \(j-i \geq m + 3\)。
枚举字符串末尾 \(x \in U\),考虑从 \(m+3\) 位填到 \(n-1\) 位。记 \(f_i\) 表示填到第 \(i\) 位,且下一位可以填 \(u\) 的方案数。转移形如 \(f_i = (k-m-3)f_{i-1} + (k-m-2)^{m+2}f_{i-m-3}\),顺着推含义是要么 \(i+1\) 位填的不是 \(x\),要么 \(i+1\) 填了 \(x\) 且后 \(m+2\) 位全都不是 \(x\)。
当 \(x\) 不在给定前缀中时,贡献即为 \(f_{n-1}\),否则考虑 \(x\) 在前缀第 \(i\) 位,则前缀需要先填 \(x\) 步,所以答案是 \(f_{n-1-i} \times (k-m-2)^{i}\)。
复杂度 \(O(n+ mq)\)。
CF2049F
显然 \(S\) 符合条件当且仅当 \(\operatorname{MEX}(S)=2^k\)。
对于每个 \(k\) 希望维护的是单点修改,查询最长连续段使得段内 \(0\) 到 \(2^k-1\) 每个数都出现过。
注意到操作只有加正数,从后往前做就变成了只有 \(0 \rightarrow 1\) 的形式,启发式合并就行了。
直接用 set 维护合并可能是三个 \(\log\) 的,换成哈希表就是两个 \(\log\) 了。
CF2075F
不难注意到一个区间是好的当且仅当左端点是严格最小值,右端点是严格最大值。
又不难注意到答案区间右端点必然是序列的后缀最大值,左端点必然是前缀最小值。
直接对后缀最大值扫描线,只需要维护区间加全局最大值。

浙公网安备 33010602011771号