先放一下我的代码,看不看随意,建议直接划到最下面。
#include <cstdio>
#include <cstring>
#include <algorithm>
#define int long long
using namespace std;
int read()
{
int a = 0,x = 1;char ch = getchar();
while(ch > '9' || ch < '0') {if(ch == '-') x = -1;ch = getchar();}
while(ch >= '0' && ch <= '9') {a = a*10 + ch-'0';ch = getchar();}
return a*x;
}
const int N=1e6+7,inf = 1e18+7;
int n,m,a[N],s[N],f[N],g[N],stk[N];
double slope(int p,int q)
{
// printf("%d %d\n",s[p],s[q]);
return 1.0*((s[q]-1)*(s[q]-1) + f[q] - (s[p]-1)*(s[p]-1) - f[p])/(s[q]-s[p]);
}
void calc(int val)
{
for(int i = 1;i <= n;i ++) f[i] = -inf,g[i] = 0;
int l=1,r=1;stk[1] = 0;
for(int i = 1;i <= n;i ++) {
while(l<r && slope(stk[l],stk[l+1]) < 2*s[i]) ++l;
f[i] = f[stk[l]] + (s[i]-s[stk[l]]+1)*(s[i]-s[stk[l]]+1) + val;g[i] = g[stk[l]] + 1;
while(l<r && slope(stk[r],i) < slope(stk[r-1],stk[r])) --r;
stk[++r] = i;
}
}
signed main()
{
// freopen("random.in","r",stdin);
// freopen("sol.out","w",stdout);
n = read(),m = read();
for(int i = 1;i <= n;i ++) a[i] = read();
for(int i = 1;i <= n;i ++) s[i] = s[i-1] + a[i];
int l = 0,r = inf,mid,ans=0;
while(l<=r) {
mid = l+r>>1;calc(mid);
if(g[n] <= m) ans = mid,r = mid-1;
else l = mid+1;
}
calc(ans);
// for(int i = 1;i <= n;i ++) printf("f[%lld] = %lld ,g[%lld] = %lld\n",i,f[i],i,g[i]);
printf("%lld",f[n] - m*ans);
return 0;
}
我这份代码中输出的是 f[n]-ans*m
,但是我想的是 f[n] 里面应该是有 g[n] 个多余的 m,所以一开始写的是 f[n]-g[n]*ans
,但是惨遭 90pts,wa10 。那么这两者区别确实挺显然 (不是),到底哪一种是正确的呢?