zsyzlzy

导航

 

这是一道猥琐的题。

方法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\n",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\n",s-f[n]);
    }
    return 0;
}
posted on 2019-07-02 11:31  zsyzlzy  阅读(75)  评论(0编辑  收藏  举报