为什么这道题维护下凸壳可以AC
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e5+5,M=255;
LL s[N],f[N][M];
int l,r,Q[N],ans[N][M];
long double X(int j){return s[j];}
long double Y(int j,int k){return (f[j][k-1]-s[j]*s[j]);}
long double slop(int j1,int j2,int k){
if(X(j1)==X(j2))return -1e18;
return (Y(j2,k)-Y(j1,k))/(X(j1)-X(j2));
}
int main(){
int m,n;scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%lld",&s[i]);
s[i]+=s[i-1];
}
for(int k=1;k<=m;k++){
l=1,r=1;Q[1]=0;
for(int i=1;i<=n;i++){
while(l<r&&slop(Q[l],Q[l+1],k)<=s[i])l++;
int j=Q[l];
f[i][k]=f[j][k-1]+(s[i]-s[j])*s[j];
ans[i][k]=j;
while(l<r&&slop(Q[r-1],Q[r],k)>=slop(Q[r],i,k))r--;
Q[++r]=i;
}
}
printf("%lld",f[n][m]);
puts("");
while(m){
printf("%d ",ans[n][m]);
n=ans[n][m],m--;
}
return 0;
}
而维护上凸壳就WA两个点?
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e5+5,M=255;
LL s[N],f[N][M];
int l,r,Q[N],ans[N][M];
long double X(int j){return s[j];}
long double Y(int j,int k){return (f[j][k-1]-s[j]*s[j]);}
long double slop(int j1,int j2,int k){
if(X(j1)==X(j2))return -1e18;
return (Y(j2,k)-Y(j1,k))/(X(j2)-X(j1));
}
int main(){
int m,n;scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%lld",&s[i]);
s[i]+=s[i-1];
}
for(int k=1;k<=m;k++){
l=1,r=1;Q[1]=0;
for(int i=1;i<=n;i++){
while(l<r&&slop(Q[l],Q[l+1],k)>=(-s[i]))l++;
int j=Q[l];
f[i][k]=f[j][k-1]+(s[i]-s[j])*s[j];
ans[i][k]=j;
while(l<r&&slop(Q[r-1],Q[r],k)<=slop(Q[r],i,k))r--;
Q[++r]=i;
}
}
printf("%lld",f[n][m]);
puts("");
while(m){
printf("%d ",ans[n][m]);
n=ans[n][m],m--;
}
return 0;
}