bzoj1010 斜率优化

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>


using namespace std;
typedef long long ll;
const int maxn = 50000+10;
ll dp[maxn],s[maxn],q[maxn];


double cal(int i,int j) {
       return (double)(dp[j]+s[j]*s[j]-dp[i]-s[i]*s[i])/(double)(s[j]-s[i]);
}


int main() {
    int n,l;
    scanf ("%d%d",&n,&l);
    l++;
    s[0] = 0; // s[i]为x,dp[i]+s[i]*s[i]为y,队列存i才能同时得到x,y
    for (int i = 1; i <= n; i++) { scanf ("%lld",&s[i]), s[i] += s[i-1]; }
    for (int i = 1; i <= n; i++) s[i] += i; //原本也应该是(s[i]-s[q[head]]+i-q[head]+1-l)*(s[i]-s[q[head]]+i-q[head]+1-l)
    int head = 1, tail = 1;//不妨另是s[i] = s[i]+i, l = l+1 ,这样简化等式,同时解决了存一个的特殊情况
    q[1] = 0; 
    for (int i = 1; i <= n; i++) {
        while(head < tail && cal(q[head],q[head+1]) <= 2*(s[i]-l)) head++;
        dp[i] = dp[q[head]]+(s[i]-s[q[head]]-l)*(s[i]-s[q[head]]-l); 
        while(head < tail && cal(q[tail-1],i) <= cal(q[tail-1],q[tail])) tail--;
        q[++tail] = i;
    }
    printf ("%lld\n",dp[n]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/kwahia/article/details/81056586