斜率優化dp

推薦學習博客:https://www.cnblogs.com/orzzz/p/7885971.html

題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=3507

#include <bits/stdc++.h>
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define sqr(x) ((x)*(x))
#define ll long long
using namespace std;
const int N = 3e6+10000;
const int mod = 1e9;
int n,m;
ll s[N],sum[N],dp[N];
int Q[N];
ll Y(int i, int j) {return dp[j]+sqr(sum[j])-dp[i]-sqr(sum[i]);}  //求Y的差
ll X(int i, int j) {return sum[j]-sum[i];}                        //求X的差
int main() {
    while(cin>>n>>m) {
        rep(i, 1, n) {
            cin>>s[i];
            sum[i] = sum[i-1] + s[i];
        }
        int l=1,r=1;
        Q[1]=0;
        dp[0]=0;
        rep(i, 1, n) {                                                    //用相乘的方法判斷分數大小
            while(l<r&&Y(Q[l],Q[l+1])<=2*sum[i]*X(Q[l],Q[l+1]))l++;       //維護隊首(刪除非最優決策)
            int x = Q[l];                                                 //取出隊列中最優元素j
            dp[i] =  dp[x] + sqr(sum[i]-sum[x]) + m;                      //計算dp
            while(l<r&&Y(Q[r],i)*X(Q[r-1],Q[r]) <= Y(Q[r-1],Q[r])*X(Q[r],i))r--; //維護隊尾(維護下凸包性質)
            Q[++r]=i;                                                       //入隊
        }
        cout<<dp[n]<<endl;
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章