算法竞赛复健记录

高三学了一年文化课感觉已经不会算法竞赛了,开个博客记录一下复健历程。

CF1662F

题意:有 \(n \le 200000\) 个点,每个点有能量 \(p_i\),消息能从 \(i\) 传到 \(j\) 当且仅当 \(|i - j| \le \min(p_i, p_j)\),求消息从 \(a\) 点传到 \(b\) 点至少需要经过几个点。

考虑把点按 \(p_i\) 降序依次插入某个数据结构 \(S\)。当 \(i\) 要插入的时候,将 \(i\)\(\{j \mid j \in S \land i - p_i \le j \le i + p_i\}\) 里的点连边。这里选择可持久化线段树作为 \(S\),用线段树优化建图的方式连边。时空复杂度是 \(O(n \log n)\),但是由于实现得不好 MLE 了。

题解的一种做法比较巧妙,直接用线段树优化了 BFS 的过程。本题相当于每条边长度是 1,所以 BFS 时让每个点只访问一遍就可以保证正确性和时间复杂度。对当前 BFS 到的点 \(i\),它能走到 \(j\) 当且仅当 \(j \in [i - p_i, i) \land i \le j + p_j\),或者 \(j \in (i, i + p_i] \land i \ge j - p_j\)。对前一情况,用一个支持单点修改、查询区间最大值的线段树 \(S\),令每个 \(S_j = j + p_j\),当从 \(i\) 能走到 \(j\) 时,即 \(S.\max[i - p_i, i) \ge i\),就把 \(j = S.\operatorname{argmax}[i - p_i, i)\) 从线段树里删去,并将 \(j\) 加入 BFS 的队列。后一情况同理。这样的时间复杂度是 \(O(n \log n)\),空间复杂度是 \(O(n)\),常数也小,不会 MLE。

CF1765J

题意:有一个 \(n \times n\) 的矩阵 \(c\),其中 \(c_{i,j} = |a_i - b_j|\),有两种操作:

  1. 将矩阵一行或一列的的元素减去(加上)\(x\),代价为 \(x\)\(-x\)
  2. 将矩阵一个位置的元素减去 \(x\),代价为 \(x\),要求 \(x>0\)

求将该矩阵所有元素变成 0 所需的最小代价。

设第 \(i\) 行做了 \(p_i\) 的操作,第 \(j\) 列做了 \(q_j\) 的操作(\(p_i, q_j \in \mathbb R\))。我们希望最大化 \(\sum_{i=1}^n (p_i + q_i)\),因为操作 1 显然比操作 2 更优。这可以写成一个线性规划问题:

\[\begin{gather*} \text{maximize} \quad & \sum_{i=1}^n (p_i+q_i) \\ \text{subject to} \quad & p_i + q_j \le c_{i,j} \quad \forall i, j \end{gather*} \]

考虑其对偶问题:

\[\begin{gather*} \text{minimize} \quad & \sum_{i,j}\lambda_{i,j}c_{i,j} \\ \text{subject to} \quad & 1 = \sum_j \lambda_{i,j} \quad \forall i \\ & 1 = \sum_i \lambda_{i,j} \quad \forall j \\ & \lambda_{i,j} \ge 0 \end{gather*} \]

可以只考虑 \(\lambda_{i,j} \in \{0, 1\}\) 的情况。这相当于从 \(c\) 的每行每列选恰好一个元素,即选出一个排列 \(p\),使得 \(\sum_i c_{i, p_i} = \sum_i |a_i - b_{p_i}|\) 最小。显然选择 \(a,b\) 同序的排列最优(即,选择的排列满足 \(a_i \le a_j \iff b_{p_i} \le b_{p_j}\)),那么将 \(a, b\) 排序即可。

QOJ1643

写成线性规划问题如下:

\[\begin{gather*} \text{maximize} \quad & \sum_{i=1}^n p_i a_i \\ \text{subject to} \quad & |a_i - a_{i-1}| \le 1 \\ & a_0 = a_{n+1} = 0 \\ & a_i \ge 0 \end{gather*} \]

转为对偶问题:

\[\begin{gather*} \text{minimize} \quad & \sum_{i=1}^{n+1} |c_i| \\ \text{subject to} \quad & c_{i+1}-c_i \le -p_i \end{gather*} \]

\(f_k(x)\) 表示当 \(c_k = x\)\(\sum_{i=1}^k |c_i|\) 的最小值,那么有转移

\[\begin{gather*} f_1(x) = |x|\\ f_k(x) = |x| + \min_{y - p_{k - 1} \ge x} f_{k-1}(y) \end{gather*} \]

再令 \(g_k(x) = f_k(x - \sum_{i=1}^{k-1})\),有转移

\[\begin{gather*} g_1(x) = |x|\\ g_k(x) = \left|x-\sum_{i=1}^{k-1}p_i\right| + \min_{y \ge x} g_{k-1}(y) \end{gather*} \]

\(g\) 的转移可以用 slope trick 优化,时间复杂度 \(O(n \log n)\)

值得一提的是,直接在原问题上转移会得到一模一样的做法,见:https://codeforces.com/blog/entry/90956?#comment-794463

CF GYM 103107 I

博弈论

参考 Sprague–Grundy theoremNimber

  • 公平组合游戏等价于(等价的定义见上述链接)一个 Nim 游戏
  • Nim 游戏中,状态 \(x\) 可以到达的状态集合为 \(S\),则 \(\newcommand\SG{\operatorname{SG}}\SG(x) = \operatorname{mex}\{\SG(y) : y \in S\}\)
  • Nim-和(相当于对 Nim 游戏做笛卡尔积?)具有交换律结合律。
    \(a + b = \{a' + b : a' \in a\} \cup \{a + b' : b' \in b\}\)
    \(\SG(a + b) = \operatorname{mex}\left(\{\SG(a' + b) : a' < a\} \cup \{\SG(a + b') : b' < b\}\right) = \SG(a) \operatorname{xor} \SG(b)\)

平衡树

做题的时候需要写一种平衡树,支持比较两个元素的序关系,于是想到了后缀平衡树用的那种将节点映射到实数上的写法,可是已经看不懂自己写的代码了...

现在看懂了,当时用 fhq-treap 实现的,为了维护元素到实数的映射,插入元素的时候不能 split 再 merge,而是要找到插入的位置,然后把那个子树的映射重构。这样做的复杂度期望是 \(O(n \log n)\) 的,因为每个元素只会被其祖先重构,而 treap 的树高是由随机性保证 \(O(\log n)\) 的。

Tarjan 算法求强连通分量

更新 low 的时候注意:搜索到横叉边的时候,如果点在栈中则要更新 low,这里的栈不是 dfs 搜索栈,而是维护所有 还未确定所属强连通分量的点 的栈。

线性规划

Lagrange 对偶

最优化问题

\[\begin{aligned} \text{minimize}_{x \in X} \quad &f(x) \\\\ \text{subject to} \quad &g(x) \ge 0 \end{aligned}\]

其中 \(f: X \to \mathbb{R}\) 是目标函数,\(g: X \to \mathbb{R}^c\) 是约束函数。该问题的拉格朗日对偶是:

\[\begin{aligned} \text{maximize}_{\lambda \in \mathbb{R}^c} \quad &t(\lambda) = \min_{x \in X} [f(x) - \lambda^\top g(x)] \\\\ \text{subject to} \quad &\lambda \ge 0 \end{aligned}\]

注意到有 \(t(\lambda) = \min_{x \in X} [f(x) - \lambda^\top g(x)] \le f(x)\),因此 \(t(\lambda)\) 给出了 \(f(x)\) 的下界,而对偶实则是最大化该下界。

线性规划对偶

\[\begin{gather*} \max\limits_{x,y,z} & c^\top x + d^\top y + f^\top z & \overset{\text{dual}}{\iff} & \min\limits_{\lambda,\eta,\mu} & p^\top \lambda + q^\top \eta + r^\top \mu \\ s.t. & Ax+By+Cz \leq p & & s.t. & \lambda \geq 0 \\ & Dx + Ey + Fz \geq q & & & \eta \leq 0 \\ & Gx + Hy + Jz = r & & & \mu\text{ free} \\ & x \geq 0 & & & A^\top \lambda + D^\top \eta + G^\top \mu \geq c \\ & y \leq 0 & & & B^\top \lambda + E^\top \eta + H^\top \mu \leq d \\ & z\text{ free} & & & C^\top \lambda + F^\top \eta + J^\top \mu = f \end{gather*}\]

线段树上二分

ac-library 及其 文档,写法是 zkw 线段树。

二分图匹配

Theorem (Hall's marriage theorem). A bipartite graph with \(n\) vertices on both sides has a perfect matching if and only if for every subset \(S\) of vertices on the left side, \(|N(S)|≥|S|\). Here, \(N(S)\) is the set of vertices on the right side that have an edge to one of the vertices of \(S\).

最大点权匹配:求二分图的带权最大匹配,其中只有一侧点有点权。做法:将点按点权排序,贪心地依次尝试增广(使用匈牙利)。

最大边权完美匹配:设 \(x_i\) 表示第 \(i\) 条边是否在匹配中,\(c_i\) 表示边权。相当于求 \(\sum x_ic_i\) 的最大值(在 \(x\) 构成匹配的约束下),写成对偶问题为求 \(\sum h_i\) 的最小值,其中 \(h_u + h_v \ge c_e \forall e = (u, v)\),这里的 \(h\) 称为顶标。根据互补松弛定理,\(h_u + h_v = c_e \Leftarrow x_e = 1\).

QOJ9372

\(S\) 的前缀函数为 \(\pi\),记 \(\Pi_i = \{\pi^k(i) : k \in \mathbb N\}\),其中 \(\pi^0(i)=i,\pi^{k+1}(i)=\pi(\pi^k(i))\)。所求为 $$\sum_{i=1}^n A_i\sum_{j \in \Pi_i-0}B_{i-j+1}$$

\(f_i=\sum_{j \in \Pi_i-0}B_{i-j+1}\),考虑如何转移。

注意到 \(\Pi_i=\{0\} \cup C\),其中 \(C \subseteq \{x+1:x\in \Pi_{i-1}\}\)。我们记 \(F_i=\{x+1 : x \in \Pi_{i-1}\} \backslash C\),那么 \(f_i=f_{i-1}-\sum_{x \in F_i} B_{i - x + 1}\)
更进一步,若 \(\pi(i) = \pi^k(i-1)+1\), 那么 \(\Pi_i=\{0\} \cup T_i\),其中 \(T_i \subseteq R_i = \{\pi^r(i-1) + 1 : r \in \mathbb N \land r \le k\}\)。现在考虑 \(R_i \backslash T_i\),可以发现 \(R_i \backslash T_i = F_{\pi_i}\)。于是我们就得到了 \(F_i=\{\pi^r(i-1)+1 : r > k\} \cup F_{\pi_i}\)

按上述方法维护 \(F_i\),复杂度应为 \(\sum_{i=1}^n |F_i|\)。注意到 \(|F_i| \le |\Pi_{i-1}|-|\Pi_i|+1\),因此 \(\sum_{i=1}^n |F_i| \le n\)

Other CP Resources

See https://t.me/CP_resource.

posted @ 2024-07-18 20:38  Ancker-0  阅读(26)  评论(0编辑  收藏  举报