杂题题解 1
CF1307G Cow and Exercise
对原图跑费用流,设每次增广后的当前的流量总和和费用总和分别为 \(v_i,c_i\),分类讨论即可得到每次询问的答案为 \(\min\left\{ \frac{c_i+x}{v_i} \right\}\)。
CF223E Planar Graph
选一个点作为汇点,每个点都有初始流量 \(1\),流量都向汇点流,那么每个点流出的流量都比流入的流量大 \(1\),于是一个环内的点的个数就是流出环的流量减去流入环的流量。以汇点为根找一棵生成树,每个点向父亲的流量就是该点的子树大小,提前对每个点的出边进行极角排序,预处理前缀和后即可快速查询。
CF708D Incorrect Flow / CF1288F Red-Blue Graph
都是有源汇上下界最小费用可行流。
CF708D Incorrect Flow CF1288F Red-Blue Graph
CF793G Oleg and chess
线段树优化建图跑费用流,扫描线的过程中动态更新线段树上的图。
[THUSCH2017] 换桌
开 \(2m\) 棵线段树优化建图跑费用流,\(m\) 棵表示从左来,\(m\) 棵表示从右来,线段树上向儿子连边时处理跨过中点的费用。
CF1100F Ivan and Burgers
离线后对询问按 \(r\) 排序,线性基中的每一位保留出现最晚的元素,在线性基上查询时,当 \(l\) 比一个元素出现时间早时,才能考虑该元素的贡献。
CF1100F Ivan and Burgers 二维情况:【NFLSPC #3】芳
[CERC2013] Escape
设二元组 \((a,b)\),表示有至少 \(a\) 的血量时,可以加 \(b\) 的血量,用可并堆维护,注意当前节点的优先级最高,要与堆顶元素不断合并来更新。
[NOI2014] 购票
线段树维护出栈序,内层再套李超线段树支持斜率优化,时间复杂度为 \(O(n\log^2n)\),空间复杂度为 \(O(n\log n)\)。也可以直接用树状数组套可撤销李超线段树,但空间复杂度为 \(O(n \log^2 n)\)。
CF925E May Holidays
对询问分块,每块先遍历一遍整棵树得到之前操作后的答案,并将该块要修改的点拿出来建虚树。虚树上的点维护到虚树父亲之间点的 \(t_i-siz_i\),\(siz_i\) 表示 \(i\) 子树内黑点个数,每次在虚树往上跳,打标记来修改,二分得到有多少个点满足 \(t_i<siz_i+tag\)。复杂度为 \(O(n\sqrt n \log n)\)。
谢特
\(LCP\) 就是后缀树上 \(LCA\) 的长度,在后缀树上用 \(01\ Trie\) 启发式合并即可。
[雅礼集训 2017 Day1] 字符串
发现 \(\sum|w|=qk\),考虑根号分治。当 \(k\) 比较小时,可以 \(O(k^2)\) 去枚举子串,在 \(s\) 的 \(SAM\) 上的对应节点计算每个子串的贡献。当 \(k\) 比较大时,可以将 \(s\) 和所有 \(w\) 一起建成广义 \(SAM\),倍增找的对应的节点来依次回答每个询问。
[雅礼集训 2017 Day7] 事情的相似度
询问就是区间前缀两两 \(LCA\) 在 \(Parent\) 树上的深度最大值。离线询问后固定右端点,用 \(LCT\) 维护 \(Parent\) 树,\(access\) 染色来更新每个前缀位置配对的 \(LCA\) 深度最大值,用树状数组维护后缀最大值即可。
CF1153F Serval and Bonus Problem
因为是实数,所以不考虑区间端点重合的情况。发现线段会被 \(2n\) 个端点划分为 \(2n+1\) 段,每段期望长度为 \(\frac{l}{2n+1}\)。考虑每段的贡献,设 \(f_{i,j}\) 表示已经考虑了 \(i\) 个端点,有 \(j\) 个左端点未匹配的方案数,得答案为合法区间的方案数除以总方案再乘上每个区间的贡献:
也可以考虑用积分来推式子,答案为:
CF1153F Serval and Bonus Problem
[JOI 2019 Final] 珍しい都市
发现一个点的独特的城市一定在其所在的最长链上,因此找到树的直径,从直径端点开始 \(dfs\),用栈维护当前点的独特的城市,先用预处理的次长链更新栈,然后进入最长链所在的儿子,再用最长链更新栈,得到当前点的答案,最后进入其他儿子。直径两个端点得到的答案取较大值为一个点的答案。
CF1284F New Year and Social Network
\(T_1\) 的一条边 \((x,y)\) 能和 \(T_2\) 的一条边 \((u,v)\) 匹配的前提条件是路径 \((u,v)\) 在 \(T_1\) 上包含边 \((x,y)\)。根据霍尔定理可以发现一定存在完美匹配,因为任意取 \(T_1\) 的 \(k\) 条边去掉后,会形成 \(k+1\) 个连通块,得 \(T_2\) 上至少有 \(k\) 条边能匹配。在 \(T_2\) 上剥叶子,在 \(T_1\) 上用并查集和倍增找对应的边匹配即可。
CF1284F New Year and Social Network
CF1039E Summer Oenothera Exhibition
贪心就是尽可能让前面的段长。先将询问离线,按要求的极差从小到大排序。设 \(nxt_i\) 表示 \(i\) 在当前极差下所在段的下一个位置,将其看作连边,用 \(LCT\) 维护,询问就是到根的点数。但 \(nxt_i\) 变化次数是 \(O(n)\) 的,直接做复杂度为 \(O(n^2\log n)\)。考虑根号分治,只在 \(LCT\) 上连 \(nxt_i \leqslant \sqrt n\) 的边,剩下的用二分和 \(ST\) 表去跳。复杂度为 \(O(n\sqrt n\log n)\)。
CF1039E Summer Oenothera Exhibition
CF1254D Tree Queries
用分块维护度数根号分治,复杂度为 \(O(n\sqrt n)\)。也有 \(O(n\log^2n)\) 的做法,每次只给重子树和子树外加权值和自身打标记,查询时跳重链来加上轻子树的贡献。
CF482E ELCA
用 \(LCT\) 维护,维护子树大小 \(siz_x\),虚子树大小(包括自身)\(s_x\),虚子树大小平方 \(s2_x\),子树内点的答案和 \(ans_x\),虚子树内点的答案和 \(val_x\),子树内 \(a_x \times s_x\) 的和 \(sum_x\),得:\(ans_x=ans_{ls}+ans_{rs}+val_x+a_x\times(s_x\times s_x-s2_x)+2\times a_x \times siz_{rs} \times s_x+2 \times sum_{ls} \times (siz_x-siz_{ls})\)。因为 \(splay\) 左子树中是祖先节点,因此就有了最后一项来算祖先的贡献。
CF1316F Battalion Strength
先排序,得答案为 \(\sum\limits_{i=1}^n\sum\limits_{j=i+1}^np_ip_j2^{i-j-1}\),考虑两两之间的贡献,用权值线段树即可维护。
CF1208G Polygons
最优情况一定存在一个点在所有多边形上,不然可以旋转。当存在正 \(x\) 边形时,所有满足 \(y\mid x\) 的正 \(y\) 边形一定存在,因此加入一个正 \(x\) 边形的贡献为 \(\varphi(x)\),取 \(3\) 到 \(n\) 的前 \(k\) 小欧拉函数即可。注意特判。
CF653F Paper task
每个位置向其作为右端点的合法的括号序列的最小左端点的上一个位置连边,最小左端点即为用栈维护后右括号匹配到的左括号,其会形成若干条链。在 \(SAM\) 上动态加字符,得以 \(i\) 为结尾的合法后缀左端点 \(\leqslant i-len_{fa_{las}}\) 时才会有贡献,在链上倍增即可。
[2017 山东一轮集训 Day5] 距离
先树上差分,转化为求到根路径上的点集和定点的距离和。设 \(x\) 到根路径上的点集为 \(p_i\),定点为 \(k\),点到根的边权和为 \(dis_x\),所求即为:\(\sum dis_{p_i}+dis_{k}\times dep_x-\sum dis_{lca(p_i,k)}\)。只有最后一项不好求,发现其可以用 [LNOI2014] LCA 中的方法求出,可持久化线段树维护即可,区间加用标记永久化实现。
[SDOI2018] 战略游戏
建出圆方树,设圆点权值为 \(1\),方点权值为 \(0\),所求即为点集形成的最小连通块的权值和减去点集大小。
[HAOI2018] 反色游戏
设解异或方程组后自由元个数为 \(cnt\),答案即为 \(2^{cnt}\)。当图合法时,即每个连通块黑点个数为偶数时,得其答案为 \(2^{m-n+p}\),其中 \(p\) 为连通块个数,考虑对每个连通块取生成树,对于非树边的任意一个方案,树边都有唯一一个合法方案与之对应。严谨的说就是矩阵的秩为 \(n-p\),因此自由元个数为 \(m-n+p\)。用圆方树维护后解决多次询问。
[JZOI-1] 拜神
离线询问固定右端点,在 \(Parent\) 树上维护每个子串上一次的出现位置,发现需要像 \(access\) 一样对当前节点到根的节点进行染色,像 [雅礼集训 2017 Day7] 事情的相似度 一样做即可,需要区间取 \(\max\)、区间和公差为一的等差数列取 \(\max\) 和单点查询,用两棵线段树来维护。
[2017 山东一轮集训 Day5] 字符串
对每个串建出 \(SAM\),当一个 \(SAM\) 上的节点没有 \(c\) 的转移时,就将其连向下一个 \(SAM\) 起始节点 \(c\) 的转移指向的点。在这样形成的 \(DAG\) 上统计路径条数即为答案。
[2017 山东一轮集训 Day2] Pair
将 \(b_i\) 从小到大排序,发现对于每个 \(a_i\) 能匹配的 \(b_i\) 都是一段后缀。对每个位置维护 \(c_i-i\),\(c_i\) 表示 \(b_i\) 能和当前多少个 \(a_i\) 匹配。线段树区间加,维护最小值,用霍尔定理判定即可,有完美匹配当且仅当最小值 \(\geqslant 0\)。
[2017 山东一轮集训 Day4] 棋盘
源点 \(\rightarrow\) 列连通块 \(\rightarrow\) 点 \(\rightarrow\) 行连通块 \(\rightarrow\) 汇点。跑费用流,拆边处理费用,即 \(\binom{i+1}{2}-\binom{i}{2}=i\)
[2017 山东一轮集训 Day4] 基因
对于每个右端点求出左端点的答案,在可持久化线段树上回答即可。考虑新加入一个右端点的贡献,一个位置的所有回文后缀可以划分为 \(O(\log n)\) 个等差数列,对每个等差数列一起处理即可,发现其贡献恰好为区间加 \(1\)。在 \(PAM\) 查询子树最大值即可得到一个串上一次的出现位置,用线段树维护即可。
[2017 山东一轮集训 Day5] 苹果树
先用折半搜索求出有用的苹果个数为 \(i\) 的合法方案数 \(s_i\),发现求出恰好有 \(i\) 个有用的苹果的生成树个数 \(f_i\) 后,\(\sum f_is_i\) 即为答案。设 \(g_i\) 为钦定有 \(i\) 个有用的苹果的生成树个数,其可以用矩阵树定理来求,连边方式为:有用 \(\longleftrightarrow\) 有用,有用 \(\longleftrightarrow\) 坏,没用 \(\longleftrightarrow\) 坏,坏 \(\longleftrightarrow\) 坏,得 \(g_i=\sum\limits_{j\leqslant i}\binom{i}{j}f_j\),二项式反演即可。
完全图的最小生成树计数
每次将当前点集按最高位是 \(0\) 是 \(1\) 划分为两个点集,两个点集递归处理后在两个点集间选一条权值最小的边相连,不难发现这样得到的树就是最小生成树。整个过程可以用 \(01\ Trie\) 来实现,找最小边就是在 \(01\ Trie\) 上贪心。到叶子节点时,若其有 \(n\) 个点,其方案数为完全图生成树个数 \(n^{n-2}\)。复杂度为 \(O(n\log^2 n)\)。
CF1325F Ehab's Last Theorem
建出 \(dfs\) 树,按经过的方向给每条边定向,得非树边只有返祖边。设 \(S=\left\lceil \sqrt n \right\rceil\),当某条非树边 \((x,y)\) 满足 \(dep_x-dep_y \geqslant S-1\) 时就找到一个大小至少为 \(S\) 的环了。不存在这样非树边时,对每个点按 \(dep_x \bmod S-1\) 的值分类,因为非树边都满足 \(dep_x-dep_y < S-1\),因此每一类点都是独立集,由抽屉原理得一定存在一类点个数 \(\geqslant \left\lceil \frac{n}{S-1} \right\rceil \geqslant S\)。
[雅礼集训 2017 Day4] 编码
\(01\ Trie\) 和前缀优化建图,跑 \(2-SAT\)。
[JSOI2019] 精准预测
对每个人在每个时刻的生死状态和互相限制用 \(2-SAT\) 来建图。但直接建图点数是 \(O(nT)\) 的,发现和限制无关的点是在一段链上,于是可以将这样的点缩起来处理,这样点数就是 \(O(n+m)\) 的了。\(n-1\) 减去每个点最终的生存状态能到达多少个其他点最终的死亡状态就是该点的答案,用 \(bitset\) 来优化传递闭包。建反图分批处理来优化空间。