众所周知,DP优化有单调队列优化、数据结构优化、矩阵快速幂优化、斜率优化、四边形不等式优化、决策单调性优化、凸优化等。本文讲解关于一类DP方程的三种优化情况。
其中 j ∈ [ l [ i ] , r [ i ] ] j\in [l[i],r[i]] j∈[l[i],r[i]]且 l [ i ] l[i] l[i]、 r [ i ] r[i] r[i]单调不减。 min \min min可换为 max \max max,方法相同。
对于 j , k ∈ [ [ l [ i ] , r [ i ] ] ( j < k ) j,k\in [[l[i],r[i]](j<k) j,k∈[[l[i],r[i]](j<k),若 f [ k ] f[k] f[k]不比 f [ j ] f[j] f[j]更劣(更大),则 j j j在 k k k以后的更新都不会有任何贡献,因为有 j j j的地方就有 k k k,且完全可以选 k k k而不选 j j j。因此用一个单调队列维护当前有用的转移下标即可。
时间复杂度 O ( n ) O(n) O(n)。
见
时间复杂度为 O ( n ) O(n) O(n)或 O ( n log n ) O(n\log n) O(nlogn)。
四边形不等式 w ( i + 1 , j ) − w ( i , j ) ≥ w ( i + 1 , j + 1 ) − w ( i , j + 1 ) w(i+1,j)-w(i,j)\ge w(i+1,j+1)-w(i,j+1) w(i+1,j)−w(i,j)≥w(i+1,j+1)−w(i,j+1)
这个性质说明,对于更大的 j j j, w ( ) w() w()随着 i i i增长的速度越慢。因此对于 k > j k>j k>j,如果从 k k k转移不劣于从 j j j转移,那么 j j j在 k k k转移以后就没用了,因为随着 i i i的增加 w ( i , j ) w(i,j) w(i,j)只会比 w ( i , k ) w(i,k) w(i,k)越来越差。即 f [ i ] f[i] f[i]的决策点是单调右移的,即决策单调性。
一般有两种方法来实现:
考虑每个决策点能更新哪些状态。我们枚举 1 1 1到 n n n的决策点来更新后面的状态。由于决策单调性,每次更新后,决策点数列是单调不减的。因此每次更新的位置是一个区间 [ k i , n ] [k_i,n] [ki,n]。于是我们用一个栈维护从左到右的连续相同的决策点块,每次更新时从栈顶开始检查,如果新决策比原决策块完全更优就把原决策块弹掉,否则二分原决策块区间找到从哪个点开始新决策更优。最后将新决策块入栈。
每个决策最多入栈、出栈一次,因为用了二分,时间复杂度为 O ( n log n ) O(n\log n) O(nlogn)。
struct decis {
int a, l, r; // 决策点位置,决策块管辖区间
}S[maxn];
int top;
//...
{
top = 0;
S[top++] = (decis){0, 0, n-1}; // 第一个决策块
for(int i = 1; i < n; i++) {
while(top) {
decis ctop = S[top-1];
int ftop = f[ctop.a] + calc(), fnew = f[i] + calc(); //calc()为分别用ctop.a和i更新ctop.l的代价
if(ftop > fnew) top--; else break;
}
if(top) {
int l = S[top-1].l, r = S[top-1].r+1;
while(l < r) {
int mid = l + r >> 1;
int ftop = f[S[top-1].a] + calc(), fnew = f[i] + calc(); //calc()为分别用S[top-1].a和i更新mid的代价
if(ftop > fnew) r = mid; else l = mid+1;
}
// 此时l的值是第一个新块较优的位置
if(l <= S[top-1].r) {
decis o = S[top-1]; top--;
S[top++] = (decis){o.a, o.l, l-1};
}
if(l <= n-1) S[top++] = (decis){i, l, n-1};
}else S[top++] = (decis){i, k-1, n-1};
}
for(int i = 0; i < top; i++) for(int j = S[i].l; j <= S[i].r; j++) f[j] = f[S[i].a] + calc();
}
考虑分治处理每个点的决策点。设当前在处理 [ l , r ] [l,r] [l,r]的决策点,并已知可能的决策点区间为 [ L , R ] [L,R] [L,R]。设 m i d = l + r 2 mid=\frac{l+r}{2} mid=2l+r,则先暴力求出 m i d mid mid的决策点 p p p(范围肯定是 [ L , m i d ] [L,mid] [L,mid]),然后分治处理两边,显然 [ l , m i d ] [l,mid] [l,mid]的决策点在 [ L , p ] [L,p] [L,p],而 [ m i d + 1 , r ] [mid+1,r] [mid+1,r]的决策点在 [ p , R ] [p,R] [p,R]。复杂度为 O ( n log n ) O(n \log n) O(nlogn)。
Upd on 2018.11.26
区间单调性 对于所有区间 [ i , j ] [i,j] [i,j]包含 [ i ′ , j ′ ] [i',j'] [i′,j′],有 w ( i , j ) > w ( i ′ , j ′ ) w(i,j)>w(i',j') w(i,j)>w(i′,j′)。
若 w ( i , j ) w(i,j) w(i,j)满足四边形不等式和区间单调性,则决策点满足区间单调性。因此枚举决策点的时候只用从之前的决策点之间枚举。类似四边形不等式优化区间DP,复杂度从 O ( n 3 ) O(n^3) O(n3)降为 O ( n 2 ) O(n^2) O(n2)。
例题:IOI2000 邮局
BZOJ3675 POJ1160 BZOJ1492 HDU3480 BZOJ2726 HDU2829 BZOJ1791 HDU3516
2018.11.30 DP凸优化