bzoj1010-[HNOI2008]玩具裝箱toy
阿新 • • 發佈:2018-10-31
斜率優化.
發現
\[ dp[i] = min(dp[j]+(i−j−1+sum[i]−sum[j]−L)^2 (j<i)\]
即
\[ dp[i] = min( -2*(sum[i]+i-l-1)*(sum[j]+j)+dp[j]+(sum[j]+j)^2 ) +(sum[i]+i-l-1)^2 \]
其中 \(2*(sum[i]+i-l-1)\), \((sum[j]+j)\) 都是單調的,因此可以斜率優化.
雙端佇列維護下凸殼.
#include<cstdio> #include<iostream> #include<cmath> #include<cstring> #include<algorithm> #include<set> #include<map> using namespace std; #define rep(i,l,r) for(register int i=(l);i<=(r);++i) #define repdo(i,l,r) for(register int i=(l);i>=(r);--i) #define il inline typedef double db; typedef long long ll; //--------------------------------------- const int nsz=5e4+5; ll n,l,sum[nsz],dp[nsz]; int qu[nsz],qh=1,qt=0; il ll p2(ll v){return v*v;} ll x(int p){return sum[p]+p;} ll y(int p){return dp[p]+p2(sum[p]+p);} ll k(int p){return 2*(sum[p]+p-l-1);} db slope(int p1,int p2){return ((db)y(p2)-y(p1))/((db)x(p2)-x(p1));} ll sol(){ dp[0]=0; qu[++qt]=0; ll k0; rep(i,1,n){ k0=k(i); while(qh<qt&&slope(qu[qh],qu[qh+1])<k0)++qh; dp[i]=-k0*x(qu[qh])+y(qu[qh])+p2(sum[i]+i-l-1); while(qh<qt&&slope(qu[qt-1],qu[qt])>slope(qu[qt],i))--qt; qu[++qt]=i; } // rep(i,1,n)cout<<dp[i]<<' '; // cout<<'\n'; return dp[n]; } int main(){ ios::sync_with_stdio(0),cin.tie(0); cin>>n>>l; rep(i,1,n){ cin>>sum[i],sum[i]+=sum[i-1]; } cout<<sol()<<'\n'; return 0; }