斜率优化dp学习

 http://acm.hdu.edu.cn/showproblem.php?pid=3507

解释:当且仅当g【j,k】程璐,j对dp【i】的更新由于k对dp【i】的;

解释:对于第2点,因为单调队列维护的要是斜率上升的数据结构;所以要做此循环

   对于第3点,因为是斜率上升的数据结构,所以如果满足持续有条件成立,就会一直优下去,知道条件不满足(就好像bst里的前驱一样)

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
inline ll read(){
    ll sum=0,x=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-')
            x=0;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
        sum=(sum<<1)+(sum<<3)+(ch^48)*1ll,ch=getchar();
    return x?sum:-sum;
}
inline void write(ll x){
    if(x<0)
        putchar('-'),x=-x;
    if(x>9)
        write(x/10);
    putchar(x%10+'0');
}
const int M=5e5+5;
ll dp[M],a[M];
int que[M],n,m;
ll ans(int i,int j){
    return dp[j]+(a[i]-a[j])*(a[i]-a[j])+m;
}
ll zi(int i,int j){
    return dp[i]+a[i]*a[i]-(dp[j]+a[j]*a[j]);
}
ll mu(int i,int j){
    return (a[i]-a[j]);
    
}
int main(){
    while(~scanf("%d%d",&n,&m)){
        for(int i=1;i<=n;i++){
            a[i]=read();
            a[i]+=a[i-1];
        }
        dp[0]=a[0]=0;
        que[1]=0;
        int head=1,tail=1;
        for(int i=1;i<=n;i++){
            while(head+1<=tail&&zi(que[head+1],que[head])<=2ll*a[i]*mu(que[head+1],que[head]))
                head++;
            dp[i]=ans(i,que[head]);
            while(head+1<=tail&&zi(i,que[tail])*mu(que[tail],que[tail-1])<=zi(que[tail],que[tail-1])*mu(i,que[tail]))
                tail--;
            que[++tail]=i;
        }
        write(dp[n]);
        putchar('\n');
    }
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/starve/p/10909356.html
今日推荐