【解题思路】
设s[i]=i+∑c[j](j∈[1,n]∩N)
易得转移方程f[i]=min{f[j]+(s[i]-s[j]-L-1)2},朴素算法复杂度O(n2)。
考虑斜率优化:记T[i]=s[i]+L+1
若成立f[j]+(s[i]-s[j]-L-1)2<=f[k]+(s[i]-s[k]-L-1)2(j<k)
<=>f[j]+(s[i]-T[j])2<=f[k]+(s[i]-T[k])2
<=>(f[j]+T[j]2)-(f[k]+T[k]2)<=2*s[i]*(T[j]-T[k])
<=>((f[j]+T[j]2)-(f[k]+T[k]2))/(T[j]-T[k])<=2*s[i]
则设P[i](T[i],f[i]+T[i]2),维护单调队列(按相邻两点斜率降序排序),当队列要加入i时,P[j]和P[k]的共存条件是(P[j]-P[k])斜率不超过2*s[i],整个单调队列呈一个下凸壳。时间复杂度O(n)。
【参考代码】
1 #include <cctype> 2 #include <cstdio> 3 #define REP(I,start,end) for(int I=(start);I<=(end);I++) 4 #define PER(I,start,end) for(int I=(start);I>=(end);I--) 5 typedef unsigned short US; 6 typedef unsigned long UL; 7 typedef long long LL; 8 typedef unsigned long long ULL; 9 typedef long double LD; 10 inline int space() 11 { 12 return putchar(' '); 13 } 14 inline int enter() 15 { 16 return putchar('\n'); 17 } 18 inline bool eoln(char ptr) 19 { 20 return ptr=='\n'; 21 } 22 inline bool eof(char ptr) 23 { 24 return ptr=='\0'; 25 } 26 inline int getint() 27 { 28 char ch=getchar(); 29 for(;!isdigit(ch)&&ch!='+'&&ch!='-';ch=getchar()); 30 bool impositive=ch=='-'; 31 if(impositive) 32 ch=getchar(); 33 int result=0; 34 for(;isdigit(ch);ch=getchar()) 35 result=(result<<3)+(result<<1)+ch-'0'; 36 return impositive?-result:result; 37 } 38 template<typename integer> inline int write(integer n) 39 { 40 integer now=n; 41 bool impositive=now<0; 42 if(impositive) 43 { 44 putchar('-'); 45 now=-now; 46 } 47 char sav[20]; 48 sav[0]=now%10+'0'; 49 int result=1; 50 for(;now/=10;sav[result++]=now%10+'0'); 51 PER(i,result-1,0) 52 putchar(sav[i]); 53 return result+impositive; 54 } 55 template<typename integer> inline ULL sqr(integer n) 56 { 57 return ULL(n)*n; 58 } 59 //========================Header Template===================== 60 using namespace std; 61 int q[500010]; 62 ULL dp[500010],sum[500010],L; 63 inline ULL getDP(int i,int j) 64 { 65 return dp[j]+sqr(sum[i]-sum[j]-L); 66 } 67 inline ULL getUP(int j,int k) 68 { 69 return dp[j]+sqr(sum[j]+L)-dp[k]-sqr(sum[k]+L); 70 } 71 inline ULL getDOWN(int j,int k) 72 { 73 return sum[j]-sum[k]<<1; 74 } 75 int main() 76 { 77 int n=getint(); 78 L=getint()+1ull; 79 sum[0]=q[0]=dp[0]=0ull; 80 REP(i,1,n) 81 sum[i]=sum[i-1]+getint()+1ull; 82 int head=0,tail=1; 83 REP(i,1,n) 84 { 85 while(head+1<tail&&getUP(q[head+1],q[head])<=sum[i]*getDOWN(q[head+1],q[head])) 86 head++; 87 dp[i]=getDP(i,q[head]); 88 while(head+1<tail&&getUP(i,q[tail-1])*getDOWN(q[tail-1],q[tail-2])<getUP(q[tail-1],q[tail-2])*getDOWN(i,q[tail-1])) 89 tail--; 90 q[tail++]=i; 91 } 92 write(dp[n]); 93 enter(); 94 return 0; 95 }
We Secure, We Contain, We Protect.