题目大意:
有n个数,分成连续的若干段,每段(假设从第j个到第i个组成一段)的分数为 (X-L)^2,X为j-i+Sigma(Ck) i<=k<=j,其中L是一个常量
使各段分数的总和最小
思路:
斜率优化dp入门题
写出dp方程之后用单调队列维护凸包即可
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstdlib> 5 #include<cstring> 6 #include<algorithm> 7 #include<vector> 8 #include<queue> 9 #define inf 2139062143 10 #define ll long long 11 #define MAXN 50010 12 using namespace std; 13 inline int read() 14 { 15 int x=0,f=1;char ch=getchar(); 16 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 17 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 18 return x*f; 19 } 20 int n,m,l,r,q[MAXN]; 21 ll s[MAXN],dp[MAXN]; 22 double slop(int i,int j) {return (dp[j]-dp[i]+(s[j]+m)*(s[j]+m)-(s[i]+m)*(s[i]+m))/(2.0*(s[j]-s[i]));} 23 int main() 24 { 25 n=read(),m=read()+1; 26 for(int i=1;i<=n;i++) s[i]=s[i-1]+read(); 27 for(int i=1;i<=n;i++) s[i]+=i; 28 l=1,r=0,q[++r]=0;int t; 29 for(int i=1;i<=n;i++) 30 { 31 while(l<r&&slop(q[l],q[l+1])<=s[i]) l++; 32 t=q[l],dp[i]=dp[t]+(s[i]-s[t]-m)*(s[i]-s[t]-m); 33 while(l<r&&slop(q[r],i)<slop(q[r-1],q[r])) r--; 34 q[++r]=i; 35 } 36 printf("%lld",dp[n]); 37 }