Kinetic Tournament Tree
考虑这样一个问题:\(n\) 个一次函数 \(k_i x_i + b_i\),每个一次函数初始有 \(x_i = 0\);区间对 \(x_i\) 加正数 \(x\),区间查询 \(\max\limits_{i = l}^r k_i x_i + b_i\)。
考虑每个点维护当 \(x_i = 0\) 时值最大的函数,然后额外维护一个阈值 \(t\),表示当 \(x\) 增大到 \(t\) 时这个点的子树中至少有一个的最大函数会发生改变。这个是很好维护的,pushup 的时候对两边儿子的 \(t\) 取个 \(\min\),然后再算儿子的最大函数的交点横坐标(下取整)即可。
区间加就递归到 \(t \ge x\) 的子树然后打标记。给一次函数的 \(b_i\) 加上 \(k_i x\),阈值减少 \(x\) 即可。
正确性比较显然。复杂度经过势能分析是 \(O(n \log^3 n)\) 级别的,但是实际运行跑得很不满。
1. P5693 EI 的第六分块
考虑沿用最大子段和的线段树维护方法,即一个点维护 \((pmx, smx, ans, sum)\)。
我们把它们都看成是一次函数,然后修改阈值 \(t\) 的定义为子树内的所有这些信息的最大函数第一次发生变化的最小需要加的 \(x\)。然后套 KTT 板子即可。
2. CF1178G The Awesomest Vertex
我们记 \(A_u = \sum\limits_{v \in R(u)} a_v, B_u = \sum\limits_{v \in R(u)} b_v\),然后把子树拍平到序列。问题变为:
- 区间对 \(A_i\) 加正数
- 求 \(\max\limits_{i = l}^r |A_i| \times |B_u|\)
\(|B_u|\) 是固定的,所以可以预先取绝对值。考虑 \(|x| = \max(x, -x)\),所以开两棵 KTT 维护即可(一个的 \(b_i\) 是 \(B_i\) 另一个是 \(-B_i\))。
3. CF1830F The Third Grace
考虑 dp,设 \(f_i\) 为选第 \(i\) 个点的最大得分。这里为了方便,把第 \(i\) 个点的贡献放到往右边转移的时候再计算。
有 \(f_j = \max f_i + c_{i, j} p_i\),其中 \(c_{i, j}\) 为 \(l \le i \le r < j\) 的区间数量。
考虑扫描线,扫右端点,同时 KTT 维护 \(f_i + c_{i, j} p_i\),当 \(j \to j + 1\) 时把所有 \(r = j\) 的区间的 \([l, r]\) 的值加上 \(p_i\)。还要支持把单点修改成 \(f_i\)。套板子即可。
挺抽象的,\(O(n \log^3 n)\) 过 \(10^6\)。
4. CF573E Bear and Bowling
考虑一个贪心:每次选对答案增量最大的元素,在这个过程中的最大权值即为答案。
考虑动态维护选择第 \(i\) 个元素后答案的增量 \(f_i\)。相当于若选了 \(p\),则 \(i \in [1, p - 1], f_i \gets f_i + a_p\);\(i \in [p + 1, n], f_i \gets f_i + a_i\);\(f_p \gets -\infty\)。
容易看出这是 \(f_i = k_i x_i + b_i\) 的形式,套 KTT 板子即可。区间加 \(b_i\) 直接打标记就行。
5. P9288 [ROI 2018] Innophone
我们可以强制让 \(a, b\) 必须顶到某一个 \(x_i, y_i\),容易发现这样不会使答案变劣。
考虑枚举 \(a\) 然后扫描线,维护有哪些元素不满足第一个条件,KTT 维护 \(b\) 取每个值的权值和,那么贡献就是形如区间加 \(k_i\)。
6. CF436F Banners
扫描线,需要区间加等差数列,求全局最大值。容易使用 KTT 维护。