【学习笔记】决策单调性优化 dp

基本操作

定义:形如 \(f_{i,j}= \min\limits_{k<i}f_{k,j-1}+ w(k+1,i)\)

条件:\(w(i,j)\) 满足四边形不等式,即 \(\forall a\le b\le c \le d,w(a,c)+w(b,d)\le w(a,d) +w(b,c)\)(如果是 \(\max\) 就是 \(\ge\))。

结论:定义 \(i\) 的决策点 \(pos_i\),则 \(\forall i\le j,pos_i \le pos_j\)

实现:

  1. 离线算法:分治
void furina(int l, int r, int L, int R, int t){
    if(l > r) return;
    int mid = l + r >> 1;
    ll minx = 1e18, id = 0;
    _req(i, min(mid - 1, R), L){
        if(!id || w(i, mid) < minx){
            minx = w(i, mid), id = i;
        }
    }
    dp[t][mid] = minx; 
    furina(l, mid - 1, L, id, t), furina(mid + 1, r, id, R, t);
}
  1. 单调队列
double calc(int x, int y){return 1.00 * a[x] + sqrt((double)y - x);}
int love(int l, int r, int x, int y){
    int res = r + 1;
    while(l <= r){
        int mid = l + r >> 1ll;
        if(calc(x, mid) - calc(y, mid) > eps) r = mid - 1, res = mid;
        else l = mid + 1;
    }
    return res;
}
struct node{
    int x, l, r;
};
void furino(){
    deque<node> q;
    _rep(i, 1, n){
        while(q.size() && q.front().r < i) q.pop_front();
        if(q.size()){
            dp[i] = max(0, a[q.front().x] + sqr[i - q.front().x]);
            while(q.size() && love(q.back().l, q.back().r, i, q.back().x) == q.back().l) q.pop_back();
        }
        if(q.size()){
            int t = love(q.back().l, q.back().r, i, q.back().x);
            node u = q.back(); q.pop_back(); u.r = t - 1; q.push_back(u);
            if(t < n) q.push_back({i, t, n});
        }else q.push_back({i, 1, n});
    }
}

例题

题单

好文收藏

cmd

posted @ 2024-07-03 22:14  FantasyNumber  阅读(0)  评论(0编辑  收藏  举报