斜率优化与 WQS 二分:从入门到人门

文章同步发表于我的 洛谷博客。

一、前置知识

1.1 二分答案

若一个函数 f ( x ) f(x) f(x) 具有单调性,且自变量的定义域为 x ∈ [ l , r ] x\in [l,r] x[l,r],则必然存在以下分界点 P P P,使得:

{ ∀   x ∈ [ l , P ] ,   f ( x ) = true ⁡ ∀   x ∈ ( P , r ] ,   f ( x ) = false ⁡ \begin{cases}\forall\ x\in [l,P],\ f(x)=\operatorname{true}\\\forall\ x\in (P,r],\ f(x)=\operatorname{false}\end{cases} {  x[l,P], f(x)=true x(P,r], f(x)=false

因此,对于区间 [ l , r ] [l,r] [l,r],中点为 m i d = l + r 2 mid=\dfrac{l+r}2 mid=2l+r,若 f ( m i d ) = true ⁡ f(mid)=\operatorname{true} f(mid)=true, 则 ∀   x ∈ [ l , m i d ] ,   f ( x ) = true ⁡ \forall\ x\in [l,mid],\ f(x)=\operatorname{true}  x[l,mid], f(x)=true,最优决策点必然在 m i d mid mid 右侧,即可令 l ← m i d + 1 l\leftarrow mid+1 lmid+1(在整数域上的二分,实数域则 l ← m i d l\leftarrow mid lmid)。

这样,整体复杂度为 O ( t i m e s × c h e c k ) O(times\times check) O(times×check) t i m e s times times 表示二分次数,通常为 log ⁡ n \log n logn,而 c h e c k check check 为单次判定的复杂度。

inline int Binary(int l,int r){
   //整数域的二分 
	int res=0;
	while(l<=r){
   
		int mid=(l+r)>>1;
		if(check(mid)) res=mid,l=mid+1;
		else r=mid-1;
	}
	return res;
}

inline double Binary_R(double l,double r){
   //实数域二分 
	double res=0;
	while(r-l>=eps){
   
		double mid=(l+r)/2.0;
		if(check(mid)) res=l=mid;
		else r=mid;
	}
	return res;
}

1.2 单调队列

顾名思义,单调队列是一种内部元素单调的特殊双端队列,常用于定长的区间最值问题。

例题:P1886 滑动窗口。

这里就不展开讲了,因为斜率优化会大量基于单调队列来实现。

1.3 斜率

在初中数学中,大家都应该学习过。对于平面内两点 ( x 1 , y 1 ) , ( x 2 , y 2 ) (x_1,y_1),(x_2,y_2) (x1,y1),(x2,y2),其联结所得的直线的斜率为 k = y 1 − y 2 x 1 − x 2 k=\dfrac{y_1-y_2}{x_1-x_2} k=x1x2y1y2

二、斜率优化

2.1 引入

有一类的动态规划,其状态转移方程具有以下的特性: f i = min ⁡ { f j − a i × b j } f_i=\min\{f_j-a_i\times b_j\} fi=min{ fjai×bj},即同时具有含有 i , j i,j i,j 的项 a i , b j a_i,b_j ai,bj。此时,单纯地单调队列优化 DP 就无法使用,而暴力枚举的复杂度是 O ( n 2 ) O(n^2) O(n2)

那么,有没有更优的方法,甚至做到 O ( n ) O(n) O(n) 的呢?

2.2 斜率优化 DP

斜率优化的标志通常是(个人总结):

  1. 状态通常是一维(当然也可能会出现二维)。

  2. 状态转移方程出现 a i × b j a_i\times b_j ai×bj 的项(这就排除了单调队列优化 DP 的可能)。

  3. n ≤ 1 0 6 n\le 10^6 n106,即算法复杂度是 O ( n ) O(n) O(n)

在这种情况下,就可以往斜优的方向想了。斜优的方法通常是:对于直线解析式 y = k x + b y=kx+b y=kx+b,将只关于 i i i 的部分看作定值 b b b,将只关于 j j j 的部分看作因变量 y y y,将 a i × b j a_i\times b_j ai×bj 的项看作 k x kx kx,其中 i i i 对应 k k k j j j 对应 x x x

这样,平面内的点 ( x , y ) (x,y) (x,y) 只与 j j j 有关,且只有因变量 y y y 包含 f j f_j fj,因此 ( x , y ) (x,y) (x,y) 即对应可能的决策点; k , b k,b k,b i i i 有关,且仅有 b b b 包含 f i f_i fi,因此最优化 b b b

例如上述的状态转移方程,将 min ⁡ \min min 去掉得:

f i = f j − a i × b j ,   f j = a i × b j + f i f_i=f_j-a_i\times b_j,\ f_j=a_i\times b_j+f_i fi

你可能感兴趣的:(日报,动态规划,算法)