10月杂题
P7862
答案具有单调性,考虑二分,设为 \(D\)。
如果一个连通块内有 \(\ge K\) 的点那么一定可行,有个粗略的证明:每次加进来一个数,如果能凑出的数的集合没有增大,说明已经存在一种方案使得和 \(=K\)。否则一定会增加一个集合中的数。
而对于一个 \(D \times D\) 的矩形,如果矩形内存在至少 \(4K\) 个点,则一定有解。可以按中线划分成 \(4\) 个子部分。根据鸽巢原理,至少有一个区域含有的点数 \(\ge K\)。
于是用 set 维护一下,每个点最多连出去 \(O(K)\) 条边,最后对每个连通块暴力背包即可,时间复杂度 \(O(N \log N \log V + NK \log V)\)。'
P7619
先想如何确定一个制作订单的顺序,考虑邻项交换。\((L_i, T_i)\) 在 \((L_j, T_j)\) 前面,当且仅当:
所以按 \(T\) 排序即可,第 \(i\) 个订单的收益为 \(L_i - \sum\limits_{j = 1}^i T_j\),显然 \(L_i\) 可以提出去,那么就要算 \(\sum\limits_{i = 1}^n \sum\limits_{j = 1}^i T_j = \sum\limits_{i = 1}^n T_i \times (n - i + 1)\),用权值线段树维护即可。
P6371
显然数位 dp,当 \(X\) 较小 \(\le 10^5\) 时设计 dp 状态 \(dp(i, 0/1, 0/1, 0/1, j)\) 表示还有 \(i\) 位没填,是否顶到了下界 \(A\),顶到了上界 \(B\),是否为空(全为前导 \(0\)),模 \(X\) 余数为 \(j\) 的方案数,转移好写。
当 \(X \ge 10^5\) 时直接 \(O(\dfrac{B}{X} \log B)\) 暴力 \(\textrm{check}\) 是否合法即可。
P10977
设计 dp,有 \(dp(i) = \min \{ dp(j) + \max_{k = j + 1}^i a_k\}\),考虑优化。
对于带有 \(max\) 的区间类 dp,可以想 CDQ 分治,每次对于区间 \([l, r]\),记录:
接着每次判断 \(\max\) 在左边和右边的情况,开些数组维护一下 \(dp\) 值即可。容易观察到每次移动指针,区间一定只会扩大,所以不需要线段树之类的数据结构。时间复杂度 \(O(n \log n)\)。
P9673
重要结论:交换次数是 \(O(n \log n)\) 级别的!!!
证明:假设取的 \(A[mid]\) 排在区间 \([l, r]\) 中的第 \(k\) 位,显然最多交换 \(\min(k - 1, (r - l + 1) - k)\) 次,所以设长度为 \(n\) 的区间的交换次数级别为 \(T(n)\),有:
\[T(n) = \min_{k = 1}^n \left(T(k - 1) + T(n - k) + \min(k - 1, n - k)\right) \]这是经典的启发式合并复杂度的式子,所以级别是 \(O(n \log n)\) 的。
问题在于指针移动次数可能是 \(O(n^2)\) 级别的,所以考虑优化指针移动的过程。
于是线段树二分即可,时间复杂度 \(O(n \log^2 n)\)。
P6122
容易建出费用流模型:
- 对于 \(i \in [1, m]\),建立 \(S \to p_i\) 连流量为 \(1\),费用为 \(0\) 的边。
- 对于原图的边 \((u, v)\),建立 \(u \to v\) 和 \(v \to u\) 的流量为 \(\inf\),费用为 \(1\) 的边。
- 对于每个点 \(x\),建立 \(x \to T\),流量为 \(c_x\),费用为 \(0\)。
这样每次新加进来一个 \(p_i\) 的时候重新建一遍图,然后跑 dinic 就能过 \(n \le 100\) 的部分分。考虑优化,于是模拟费用流,由于这个图是一个完全二叉树,即两点路径长度为 \(O(\log n)\),所以记 \(f(i)\) 表示 \(\textrm{argmax}_{j \in subtree(i)} \textrm{dist}(j, i)\),每次更新路径上的流量并维护一下即可。时间复杂度 \(O(n \log n)\)。
CF1175G
考虑 \(dp\),设 \(dp(i)\) 表示前 \(i\) 个分成若干段的答案,有 \(dp(i) = \min \{ dp'(j) + (i - j) \times \max_{k = j + 1}^i a_k\}\)。看到代价函数中含有区间 \(max\),于是想到 CDQ 分治。
于是类似上面 Cut the Sequence 的思路,处理出 \(max(i)\),内部套一个斜率优化即可。时间复杂度 \(O(n k \log n)\)。
CF1214G
显然存在一组解的充要条件是:存在两行 \(i, j\) 使得 \(S_i\) 和 \(S_j\) 不相互包含。
有结论:将每行按照 \(1\) 的数量从小到大排序,存在解 \(\Leftrightarrow\) 相邻两行合法。
证明:假设有 \(i < j < k\),存在 \(S_i \cup S_k \ne S_i\),并且 \(S_i \cup S_j = S_i \land S_j \cup S_k = S_j\),推出 \(S_i \cup S_k = S_i\) 与假设矛盾。原结论得证。
用 set 和 bitset 维护即可,时间复杂度 \(O(q \log n + \dfrac{n^2}{w})\)。\
ABC374F
模拟赛出了这道题的加强版,把 \(N\) 开到了 \(10^4\) 并且要求 \(O(N)\) 空间复杂度。
于是设 \(dp(i)\) 表示前 \(i\) 个完成,现在的时间为 \(T_i\) 的最小答案。考虑更新 \(dp(j)\) 的值,每次往后走一段,设当前时间为 \(pret\),走到了 \(prex\),答案为 \(prec\),设 \(nxx\) 为 \(T\) 中最后一个 \(\le pret + X\) 的下标,由于每次最多选 \(K\) 个,所以要让 \(nxx\) 对 \(prex + K\) 取 \(\min\)。每次给 \(prec\) 加上 \((nxx - prex) * T_{nxx}\) 即可,然后更新 \(pret\) 和 \(prex\) 的值。
转移的时候很好计算贡献,答案为 \(dp(n) - \sum\limits_{i = 1}^n T_n\),时间复杂度 \(O(N^2)\)。
ABC374G
首先考虑连边,问题转化为选择最少的可交路径使得一个有向有环图的每条边都被覆盖。显然一个强连通分量内的边是可以一次走完的,所以缩点后变为 DAG 的问题。
接着发现这很网络流,考虑将点转化为边,边转化为点。这样就变为选最少的可重路径使得每个点都被覆盖一次,传递闭包一下就转化为了不可重路径,点数 \(O(N^2)\),由于 \(N^2\) 只有 \(600\) 所以可过。

浙公网安备 33010602011771号