序列分治

考虑一类问题:有 \(O(n^2)\) 个区间,分别有贡献函数 \(f(l,r)\)。要在小于 \(O(n^2)\) 的时间内求 \(\displaystyle \bigotimes_{1\le l\le r\le n} f(l,r)\)(这里的 \(\otimes\) 可能是各种有结合律的运算);或者更进一步,对每个 \(l\) 分别求出 \(\displaystyle \bigotimes_{r\in[l,n]} f(l,r)\)

这要求必须每次批量计算一堆区间的贡献而不能分别计算。可以考察 \(f\) 的性质,如果能够拆贡献,就可以考虑分治计算。

具体来说,每次 \(O(k\cdot len)\) 计算当前长度为 \(len\) 分治区间下,跨越区间中点的所有区间的贡献。也就是所有 \(l\in[L,mid]\) 对所有 \(r\in(mid,R]\) 的贡献。

CDQ 分治其实是这一种分治在时间轴上进行的特例。区间可以看作每个左端点为修改、右端点为查询的区间。这里蕴含着归并的思想。

Luogu P7482

显然的观察:随便取一个地方,考虑其是否取,可以把这个区间的 \(f\) 分成两个子问题。

直接区间 DP 每次合并区间可以做到 \(O(n^2)\)。考虑分治优化,即快速合并跨越中点的区间。

\(f_x\) 表示强制不选 \(mid\) 的区间 \([\min(x,mid),\max(x,mid)]\) 的答案,\(g_x\) 表示区间 \([\min(x,mid),\max(x,mid)]\) 的答案。即快速计算:

\[\sum_{l=L}^{mid} \sum_{r=mid+1}^R \max(f_l + g_r, f_r + g_l) \]

\(l,r\) 不能分离,不好处理。一个 Trick:对每一项减去 \(g_l+g_r\)

\[=\sum_{l=L}^{mid} \sum_{r=mid+1}^R \max(f_l - g_l, f_r - g_r) + \sum_{l=L}^{mid} \sum_{r=mid+1}^R (g_l + g_r) \]

直接对两半的 \(f-g\) 排序扫一遍即可。因为这个值对不同 \(mid\) 是不同的所以不能归并排序。\(O(n\log^2n)\)

ARC066F

给定序列 \(a\),定义一个区间的权值和为 \(\frac{(r-l+1)(r-l+2)}{2}-\sum_{i=l}^r a_i\),定义选取若干个点的一种方案的权值为各极大连续被选区间的权值和。每次询问假设令 \(a_x=y\) ,权值最大方案的权值,询问之间独立。

这个题分治可以从 \(O(n^3+q)\) 优化到 \(O(n\log n+q)\) 令人感慨。

首先一个观察:每次只改变一个位置的元素且独立。可以考虑枚举是否选这个元素的答案来预处理。钦定不选元素 \(i\) 则左右两部分独立,则答案为 \(Ans(1,i-1)+Ans(i+1,n)\)。两项分别设为 \(f_{i-1},g_{i+1}\),斜率优化 DP 预处理。

考虑钦定必须选 \(i\)。这时候左右两边不独立,需要枚举 \(i\) 所在连续段的端点:

\[h_i=\max_{l\le i\le r}\{ f_{l-1}+g_{r+1} + \frac{(r-l+1)(r-l+2)}{2} -(s_r-s_l) \} \]

这里有一个重要的观察:整个式子与 \(i\) 无关。转换统计主体,其实只需要对每个区间 \([l,r]\) 算出答案,区间内 \(h\) 对其取 \(max\)。正着统计难以优化,但是考虑钦定 \(l\),对所有 \(i\ge l\)\(h_i\) 贡献。直观的想法是斜率优化找到其对应最优的 \(r\),将 \(l,r\) 的答案贡献给 \(i\in[l,r]\)。但是对于 \(i>r\) 其实也可能有贡献。

这就符合我们序列分治的形式了。遍历 \([L,mid]\) 内的点 \(j\),斜率优化找到其对应最优的在 \((mid,R]\) 的右端点来贡献即可。这样保证了每个 \(j\) 对于 \(i\in[j,mid]\) 都可以正确地贡献,因此跑完分治之后就可以对 \([1,\frac{n}{2}]\) 正确贡献。

那么 \((\frac{n}{2},n]\) 怎么办呢?考虑在分治时,也遍历 \((mid,R]\) 内每个点,同理找到最优的左端点。这样就能正确贡献右半部分了。

所有值均为正数,可以 \(O(n)\) 斜率优化,故总复杂度 \(O(n\log n)\)

posted @ 2023-08-06 20:12  音街ウナ  阅读(40)  评论(0)    收藏  举报