这是不知道什么类型的题。。。或许应该算。。。技巧型的???
刚开始的时候暴力,然后T掉了,后来想了想,改了一下,又wa掉了。。。。
先说下错误的想法:分了两类讨论,一类是n>w,一类是n<=w的。第一类想说,要保证扫描到的序列就是所求序列,所以内部先分配,多余的抛出去就好了,这一部分没有问题。但是到了第二类的时候,因为要创建新的堆,所以出现了一种问题,内部多余的,是分配出去(n-w+1)个,还是(n-w)个?这里剩余的值一直有问题。以为可以分配的好,但是实际上这类的讨论若是这种方式是不能正确解得的。
后来看了题解,很简单,就是在前后都加上了w个空位。然后用第一类的方法解得即可。
有感,,,算法应该是问题的统一讨论,既然对于第一类问题有了方法,为什么不想着把这个方法扩展到第二类中。还是太蠢了QAQ
#include <stdio.h>
#define maxn 301000
#define max 9999999999999
#define ll long long //这里要注意把数据范围改改,因为50000*50000貌似会爆int
int b[maxn];
ll sum[maxn];
int n,h,w;
ll min(ll a,ll b)
{
return a<b?a:b;
}
int main()
{
while(scanf("%d%d%d",&n,&w,&h)!=EOF)
{
int i;
ll j,k;
ll ans=max;
for(i=0;i<w;i++) sum[i]=b[i]=0;
for(i=w;i<n+w;i++)
{
scanf("%d",&b[i]);
sum[i]=sum[i-1]+b[i];
}
for(i=n+w;i<n+w+w;i++) sum[i]=sum[i-1],b[i]=0;
j=k=0;
k=(w*h);
for(i=1;i<n+w;i++)
{
int tmp=b[i-1]-h;
if(tmp>0) j-=tmp;
else k+=tmp;
tmp=b[i+w-1]-h;
if(tmp>0) j+=tmp;
else k-=tmp;
ll res=sum[i-1]+sum[n+w+w-1]-sum[i+w-1];
if(j>=k) ans=min(ans,j);
else
{
if(res>=(k-j)) ans=min(ans,k);
else continue;
}
//printf("%lld %lld %lld\n",j,k,res);
}
printf("%lld\n",ans==max?-1:ans);
}
return 0;
}