这是一道猥琐的题。
方法1.
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=4e5+10;
int n,m,q[N],l,r;
ll a[N],s[N],f[N];
ll x(int i){return a[i+1];}
ll y(int i){return a[i+1]*i-s[i]+f[i];}
bool pd(int i,int j,int k)
{
return (y(j)-y(i))*(x(k)-x(i))<(y(k)-y(i))*(x(j)-x(i));//不能加等于
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
sort(a+1,a+n+1);
for(int i=1;i<=n;i++)s[i]=s[i-1]+a[i];
for(int i=min((m<<1)-1,n);i>=m;i--)f[i]=s[i]-a[1]*i;
l=1;r=1;q[1]=m;
for(int i=m<<1,j;i<=n;i++)
{
while(l<r&&(y(q[l+1])-y(q[l]))<i*(x(q[l+1])-x(q[l])))l++;
j=q[l];
f[i]=f[j]+s[i]-s[j]-a[j+1]*(i-j);
while(l<r&&(!pd(q[r-1],q[r],i-m+1)))r--;
q[++r]=i-m+1;
}
printf("%lld
",f[n]);
}
return 0;
}
方法2.
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int size=1<<20;
inline char g()
{
static char buf[size],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,size,stdin),p1==p2)?EOF:*p1++;
}
#define g g()
template<class o>
void qr(o&x)
{
char c=g;x=0;
while(!(('0'<=c&&c<='9') || !(~c)))c=g;
while('0'<=c&&c<='9')x=x*10+c-'0',c=g;
}
const int N=4e5+10;
int n,m,q[N],l,r;
ll a[N],f[N],s;
inline ll y(int i){return a[i+1]*i-f[i];}
inline ll x(int i){return a[i+1];}
inline ll yy(int i,int j){return y(i)-y(j);}
inline ll xx(int i,int j){return x(i)-x(j);}
int main()
{
//freopen("a.in","r",stdin);
//freopen("a.out","w",stdout);
while(1)
{
qr(n);
if(!n)break;
qr(m);
s=0;
for(int i=1;i<=n;i++)
qr(a[i]),s=s+a[i];
if(m==1){puts("0");continue;}
sort(a+1,a+n+1);
for(int i=1;i<m;i++)f[i]=0;
for(int i=min((m<<1)-1,n);i>=m;i--)f[i]=a[1]*i;
l=1;r=1;q[1]=m;
for(int i=m<<1,j;i<=n;i++)
{
while(l<r&&yy(q[l+1],q[l])<=xx(q[l+1],q[l])*i)l++;
j=q[l];
f[i]=f[j]+a[j+1]*(i-j);
while(l<r&&yy(q[r],q[r-1])*xx(i-m+1,q[r])>=yy(i-m+1,q[r])*xx(q[r],q[r-1]))r--;
q[++r]=i-m+1;
}
printf("%lld
",s-f[n]);
}
return 0;
}