据说这个题的正解是斜率优化DP?
我直接贪心(这个贪心不保证正确,类似于模拟退火)
考虑优化n^2暴力
一般转移时是当当前加的价值趋近为0时转移的
我们2分找到这个点,以这个点为中心以某一半径转移DP
(数据较水,半径取10都能过)
#include<bits/stdc++.h>
#define LL long long
using namespace std;
LL dp[50004];
LL n,L;
LL su[50004];
int main() {
cin>>n>>L;
for(LL i=1; i<=n; i++) {
LL x;
scanf("%d",&x);
su[i]=su[i-1]+x;
}
if(n<=10000) {
for(LL i=1; i<=n; i++) {
dp[i]=LONG_LONG_MAX;
for(LL j=1; j<=i; j++) {
dp[i]=min(dp[i],dp[j-1]+(i-j+su[i]-su[j-1]-L)*(i-j+su[i]-su[j-1]-L));
}
}
cout<<dp[n];
} else {
for(LL i=1; i<=n; i++) {
dp[i]=LONG_LONG_MAX;
LL l=1,r=i,mid;//玄学2分优化
while(l<=r) {
mid=(l+r)/2;
if(i-mid+su[i]-su[mid-1]<L)
r=mid-1;
else
l=mid+1;
}
l=max(1ll,mid-7);//l=max(1ll,mid-500); 500更保险,但实测这样也可以
r=min(i,mid+6);//r=min(i,mid+500);
for(LL j=l; j<=r; j++) {
dp[i]=min(dp[i],dp[j-1]+(i-j+su[i]-su[j-1]-L)*(i-j+su[i]-su[j-1]-L));
}
}
cout<<dp[n];
}
return 0;
}
优秀