logo

yaohaoyou

春节

wqs 二分学习笔记

2026-01-12 Views 算法1664字9 min read

目前好像只会一些恰好选 kk 段的题目。

wqs 二分适用于解决对于一个上凸/下凸的函数 ggO(DlogV)\mathcal O(D\log V) 的复杂度内求出一个单点值 g(x)g(x),其中 DD 为求出 min/max(g(x)kx)\min/\max(g(x)-kx) 的复杂度,VV 为相邻 gg 上相邻两点斜率的范围。

具体的,我们需要使用一条直线 l:y=kx+bl:y=kx+b 来切点 (x,g(x))(x,g(x)),使得 ll 同时是凸包 g(x)g(x) 的切线,求 kk 的最值,这是网络上常见的理解,我更愿意理解为找 gk(x)=g(x)kx+bg'_k(x)=g(x)-kx+b 的最值。

观察图像可知,当 g(x)g(x) 为下凸包,kk 要求最大时,gk(x)g'_k(x) 会在 [x,x+1][x,x+1] 时取到最小值,若二分 kkargmin(gk(x))x\operatorname{argmin}(g'_k(x))\le x,则说明斜率过小(或刚好),将 l=mid+1l=mid+1,否则将 r=mid1r=mid-1argmin(f(x))\operatorname{argmin}(f(x)) 表示使函数 f(x)f(x) 取到最小值的 xx。(实际上应该求 kk 的最小值也是一样可以的。)

上凸包的情况类似,下面给几道题目。

P4983 忘情

首先要求的那个式子其实就是 (xi+1)2(\sum x_i+1)^2

fi,jf_{i,j} 表示前 ii 个数分成 jj 段的答案,则有转移式 fi,j=mink=0j1(fk,j1+(sisk+1)2)f_{i,j}=\min_{k=0}^{j-1}(f_{k,j-1}+(s_i-s_{k}+1)^2),由于 xi>0x_i>0,可以证明 fnf_n 是下凸的,要求 fn,mf_{n,m}

这和上面的类似了,考虑对函数 g(x)=fn,xg(x)=f_{n,x} 做 wqs 二分。先二分一个斜率 kk,然后需要判断 g(x)=g(x)kxg'(x)=g(x)-kx 在何处取到最小值。只需要将 kx-kx 拆到每次新开一组的时候 k-k 即可。转移可以斜率优化。总复杂度为 O(nlog2nV)\mathcal O(n\log_2nV)

P6246 [IOI 2000] 邮局 加强版 加强版

w(l,r)w(l,r) 表示区间 [l,r][l,r] 放一个邮局的距离和,fi,jf_{i,j} 表示前 ii 个村庄分 jj 段。可以发现 ww 满足四边形不等式,所以 g(x)=fn,xg(x)=f_{n,x} 为下凸函数。依旧套用 wqs 二分处理,check 时需要用决策单调性,可以使用二分队列。

CF2183H Minimise Cost

先贪心。子序列实际上可以转成从小到大排序后的子区间,负数尽量全部放一组,非正数首先选出部分组成 k1k-1 组,剩余的和负数放一组。

依旧是一个类似的转移式,令 fi,jf_{i,j} 表示前 ii 个数分为 jj 组,w(l,r)=(rl+1)(srsl1)w(l,r)=(r-l+1)(s_r-s_{l-1})fi,j=mink=0i1fk,j1+w(k+1,i)f_{i,j}=\min_{k=0}^{i-1} f_{k,j-1}+w(k+1,i)。根据上面的贪心,只有在 i=1ai0i=1 \vee a_i\ge 0 的时候需要转移枚举断电,对于 w(l,r)(l=1al0,ar0)w(l,r)(l=1\vee a_l\ge 0,a_r\ge0) 可以证明其满足四边形不等式,所以这个 ff 满足决策单调性,fnf_n 是下凸的。

然后就和上面的 p6246 一样了。

P9266 [PA 2022] Nawiasowe podziały

w(l,r)w(l,r) 表示区间 [l,r][l,r] 中所有子串中合法括号序列数量,可以证明 ww 满足四边形不等式。令 fi,jf_{i,j} 表示前 ii 个字符分成了 jj 段的方案数,则 fi,j=mink<ifk1,j1+w(k,i)f_{i,j}=\min_{k<i}f_{k-1,j-1}+w(k,i),所以 F(x)=fn,xF(x)=f_{n,x} 为下凸函数。

套路地,显示使用 wqs 二分,然后需要求 gi=minj<igj1+w(j,i)midg_i=\min_{j<i}g_{j-1}+w(j,i)-mid。因为 ww 满足四边形不等式,所以 gg 满足决策单调性,但 ww 不好直接求,并且 gg 求解过程需要在线。

发现 w(l,r)w(l,r) 在做 ll±1l\to l\pm 1rr±1r\to r\pm 1 时可以直接 O(1)\mathcal O(1) 求解,所以可以用 cdq 分治套决策单调性分治解决,复杂度为 O(nlog3n)\mathcal O(n\log^3n)。但是可以使用LARSCH/简化 LARSCH(感觉像科技)算法优化至 dp 部分只要 O(n)/O(nlogn)\mathcal O(n)/\mathcal O(n\log n),总复杂度为 O(nlogn/nlog2n)\mathcal O(n\log n/n\log^2n)

简化 LARSCH

简化 LARSCH 算法其实类似于 cdq 分治套决策单调性分治,令 optt(x)opt_t(x) 表示只考虑从 [1,t][1,t] 的转移到 xx 的最优决策,opt(x)=optx1(x)opt(x)=opt_{x-1}(x)。具体过程是定义 solve(l,r)solve(l,r) 表示已知 [1,l)[1,l)g,optg,optoptl1(r)opt_{l-1}(r),求解 [1,r][1,r]g,optg,opt

  1. i[optl1,optl1,r]i\in [opt_{l-1},opt_{l-1,r}] 求出 optl1(mid)opt_{l-1}(mid),因为 optt(x)optt(y)optt(z),x<y<zopt_{t}(x)\le opt_{t}(y)\le opt_{t}(z),x<y<z
  2. 调用 solve(l,mid)solve(l,mid)
  3. opt(i),i[l,mid]opt(i),i\in [l,mid]optl1(r)opt_{l-1}(r) 求出 optmid(r)opt_{mid}(r)
  4. 调用 solve(mid+1,r)solve(mid+1,r)

注意 1 操作中要移动 w1w1 的指针,3 操作中要移动 w2w2 的指针,可以证明整个过程中 w1w1w2w2 的指针一共只会移动 O(nlogn)\mathcal O(n\log n) 次,若两种操作移动同一对指针会退化到 O(n2)\mathcal O(n^2) 次。

EOF