一些题(十一)
[CERC2015] Juice Junctions
判断一个点对的最大流为 \(1\) 或 \(\ge2\),容易求出边双后做。接下来就要判断两个点的最大流是否为 \(3\),也就是它们是否在一个边三联通分量中。这相当于删去图中任意一条边后这两个点都在同一个边双中。于是就可以每次删边求边双,并用 hash 判断。时间复杂度 \(O(n^2)\)。
[BalticOI 2021] The short shank
对于每个 \(t_i>T\) 且若不进修隔离它最终造反的时间 \(\le T\),求出最左的隔离位置使得它最终造反时间仍 \(>T\),不妨设这个位置为 \(l_i-1\) 和 \(l_i\) 之间。那么问题转化为从 \([2,n]\) 中选 \(D\) 个关键点,使得 \([l_i,i]\) 中有关键点的 \(i\) 最多。注意到所有 \([l_i,i]\) 要么包含要么不交,即形成树形结构,于是在这个树上长链剖分贪心取即可。
[CF963E] Circles of Waiting
容易列出变量数和方程数均为 \(O(R^2)\) 的线性方程组,若直接消元,时间复杂度为 \(O(R^6)\)。但注意该图是 \((2R+1)\times (2R+1)\) 的网格图的子图,于是将变量按从上到下、从左到右排序后,在消第 \(i\) 行时只用考虑 \([i,i+2R]\times[i,i+2R]\) 这个子矩形的变化,时空复杂度 \(O(R^4)\)。当然也可以主元做到 \(O(R^3)\)。
https://codeforces.com/contest/963/submission/146990640(\(O(R^4)\))
[CF1089H] Harder Satisfiability
先按解 2-SAT 的方式建出有向图,然后 SCC 缩点。那么无解当且仅当以下条件至少一个成立:
- 2-SAT 问题无解;
- 存在一个 \(\forall\) 点能到另一个 \(\forall\) 点;
- 存在一个 \(\forall\) 点与一个编号比它小的 \(\exist\) 的在同一个 SCC 内;
于是可以线性判定。
https://codeforces.com/contest/1089/submission/146507317
[CF1096E] The Top Scorer
一个线性做法。直接枚举第一个人的分数和与他同分的人数,得:
其中 \(F(x)=\left({1-x^k\over 1-x}\right)^n\) 的系数可以通过 \(F(x)'=nF(x)\left({1\over 1-x}-{kx^{k-1}\over 1-x^k}\right)\) 来线性递推出。
https://codeforces.com/contest/1096/submission/146920398
[CF1305G] Kuroni and Antihype
新增一个 \(a\) 为 \(0\) 的点并假定它一开始就在集合中,那么每个选择自己加入集合的其它点都可以视作被新加的点拉进来的。考虑建一棵以新点为根的有根树使得每个点都被它的父亲拉进集合,那么总贡献就是每个点的权值乘上它的儿子个数减一再求和,也就是对每条树边 \((u,v)\) 边 \(a_u+a_v\) 求和然后减去 \(\sum a_u\)。于是问题转化为对每组 \(a_u \and a_v=0\) 的 \((u,v)\) 加入边权为 \(a_u+a_v\) 的边后求最大生成树,可以用高维前缀和辅助 boruvka 算法在 \(O((n+a_i)\log n\log a_i)\) 的时间内完成。
https://codeforces.com/contest/1305/submission/147254876
[CF1534H] Lost Nodes
对于给定的 \(f\),以 \(f\) 为根后 \(a,b\) 一定在根的两个不同儿子的子树中或者为根,可以进行树形 dp。设 \(f_u\) 表示若已经确定一个点在 \(u\) 的子树中,找到它的最少询问次数,\(g_u\) 表示一种最优方案的第一步。特殊地,对于叶子节点 \(u\),计 \(f_u=1,g_u=u\)。考虑转移,对于节点 \(u\) 的最优询问方案一定是,依次通过询问 \(g_v\) 来确定每个儿子是否有关键点,如果有就递归下去,如果都没有就是 \(u\)。容易发现按照儿子的 \(f\) 不降序排列一定最优,设排好序的儿子序列为 \(\{v_i\}_{i=1}^k\),那么有 \(f_u=\max\{k,\max_{i=1}^k f_{v_i}+i-1\},g_u=g_{v_1}\)。确定答案时也是对根进行类似的过程,并且可以换根 dp 求出每个给定的 \(f\) 的答案然后取最大值。时间复杂度 \(O(n)\)。
https://codeforces.com/contest/1534/submission/145812674
[CF1637H] Minimize Inversions Number
设 \(d_i\) 为仅把第 \(i\) 个元素放在最前面后逆序对的变化量,那么对于选出下标序列 \(\{x_1,\ldots,x_k\}_\le\) 进行操作,逆序对的总变化量为 \(\sum_{i=1}^k d_{x_i}+2\sum_{i=1}^k\sum_{j=i}^k [p_{x_i}>p_{x_j}]-{k\choose 2}\),因为从前往后把每个 \(x\) 提前后 \(\{p_{x_1},\ldots,p_{x_k}\}\) 会进行翻转。注意到对于 \(i<j,p_i>p_j\),若 \(i\) 被选入,那么一定存在一种最优方案使得 \(j\) 也被选入,证明可以考虑找到不满足的 \(j-i\) 最小的 \(i,j\) 进行交换调整。于是存在一个最优的方案 \(x\) 使得 \(\sum_{j=i}^k [p_{x_i}>p_{x_j}]=\sum_{j=x_i}^n [p_{x_i}>p_j]\)。那么拆一下贡献,按照 \(d_{x_i}+2\sum_{j=x_i}^n [p_{x_i}>p_j]\) 从小到大取 \(x_i\) 即可。
https://codeforces.com/contest/1637/submission/146987839
[清华集训2014] 文学
把书看成点,“批量阅读”看成半平面,那么就是要选代价和最小的半平面使得它们的并覆盖率所有点。注意到若干个半平面的并的补是一个凸集,也就是说对于所有横坐标为 \(x\) 的点,至多只用两个“有效”的半平面取覆盖它们。于是按 \(x\) 从左往右 dp,对每种横坐标记录这两个半平面是什么即可。复杂度 \(O(pn^2)\)。
https://uoj.ac/submission/535709
[UR #7] 水题走四方
通过调整,一种最优方案肯定是他从根走到一个叶子,过程中它的分身不停的传送然后遍历其它点。若某时刻他和他分身在同一个点,就将这个点记作关键点。设 \(lf_u\) 表示 \(u\) 子树中的叶子集合,\(dep_u\) 表示 \(u\) 的深度。考虑从上往下 dp,设 \(f_v\) 表示 \(v\) 是关键点并且只剩 \(v\) 的子树没访问过的最小时间。考虑枚举 \(v\) 的祖先中最近的关键点 \(u\) 进行转移,若 \(lf_u\setminus lf_v=\emptyset\),那么 \(u\) 为 \(v\) 的父亲并且 \(v\) 是 \(u\) 的唯一儿子,有 \(f_v=f_u+1\);否则记 \(lf_u\setminus lf_v\) 中最深的点为 \(x\),那么一种最优方案一定是在 \(u\) 时让分身遍历完 \(lf_u\setminus lf_v\setminus \{x\}\) 的所有点,然后分身走向 \(x\) 的同时本体从 \(u\) 走向 \(v\),注意到此时\(u\) 只可能为最深的使得 \(dep_x\ge dep_v\) 点,否则可以调整使得有更深的关键点。于是在从上往下 dfs 的过程中暴力维护一个栈找 \(u\) 即可,时间复杂度 \(O(n)\)。