1010 [HNOI2008]玩具装箱toy
斜率优化dp;
推荐学习http://www.cnblogs.com/perseawe/archive/2012/05/12/bz1010.html
看着别人的题解自己学着推,终于理解了
#include<cstdio> #include<cstring> #include<algorithm> #define ll long long #define maxn 50005 using namespace std; int q[maxn],head=0,tail=0; ll f[maxn]; ll g[maxn],s[maxn]; ll dp[maxn]; ll get_g(int k,int j,int c) { return dp[k]+(f[k]+c)*(f[k]+c)-dp[j]-(f[j]+c)*(f[j]+c); } ll get_s(int k,int j) { return 2*(f[k]-f[j]); } int main() { int n,m,xx; scanf("%d%d",&n,&m); for(int i=1; i<=n; i++) { scanf("%d",&xx); f[i]+=f[i-1]+xx; } for(int i=1; i<=n; i++)f[i]+=i; int c=1+m; q[tail++]=0; for(int i=1;i<=n;i++) { while(head<tail-1&&get_g(q[head+1],q[head],c)<=f[i]*get_s(q[head+1],q[head]))++head; int v=q[head]; dp[i]=dp[v]+(f[i]-f[v]-c)*(f[i]-f[v]-c); q[tail++]=i; for(int j=tail-2;j>head;j--) { int cc=q[j+1]; int bb=q[j]; int aa=q[j-1]; if(get_g(bb,aa,c)*get_s(cc,bb)>=get_g(cc,bb,c)*get_s(bb,aa)) q[j]=q[--tail]; else break; } } printf("%lld\n",dp[n]); return 0; }