题意:n堆积木,通过调整使得其中有连续W堆积木具有相同的高度,同时高度恰好为H,不能添加新的积木,只能移动现有的积木。可以把一个积木从一堆移动到另一堆或者新的一堆,但是不能移动到两堆之间,比如,一次移动之后,"3 2 3" 可以变成 "2 2 4" 或者 "3 2 2 1",但是不能变成"3 1 1 3"。
解题思路:首先记录n个数值的总和,然后每次以w长度对数组进行遍历,切每次对w区间长度内的数值进行处理,将每个大于H的A[i]与H的差值累加赋给t1,将每个小于H的A[i]与H的差值累加赋给t2,然后将t1,t2中较大的值与上次的ans比较取出最小值赋给ans,ans表示该w长度内满足条件时所需移动的次数,然后往下移动即t1或t2中移除一个a[i-w],然后添加一个a[i],最后输出ans即可。
Code:
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#define INT_MAX 1e9+10
typedef long long LL;
int n,w,h;
int a[200000];
int main()
{
//freopen("input.txt","r",stdin);
while(~scanf("%d%d%d",&n,&w,&h))
{
fill(a,a+200000,0);
LL sum=0,t1 = 0,t2 = 0;//t1代表高度超过H的总和,t2高度小于H的总和,sum表示所有输入a[i]值的总和
int i = 0;
for(;i<w; i++)//数组a[i]的前端增加w个0
{
a[i] = a[i]-h;//a[i]-h表示每个a[i]值与h的差值,并将该差值赋给a[i]
t2 +=-a[i];//将差值小于0的累加赋给t2保存
}
for(;i<n+w; i++)
{
scanf("%d",&a[i]);
sum +=a[i];
a[i] = a[i]-h;//将每个a[i]替换成a[i]-h的差值
}
for(;i<n+2*w; i++)
a[i] = a[i]-h;
LL ans = INT_MAX;
ans = max(t1,t2);//将t1、t2中的最大值赋给ans,ans表示每次移动的次数,
if(sum < w*h) printf("-1\n");//sum小于w*h直接输出-1
else //否则遍历后边的区间
{
for(int j = w; j<n+2*w; j++)
{
if(a[j-w] > 0) t1 -=a[j-w];//t1移除前面一个a[i]值
else t2 +=a[j-w];//t2移除后面一个a[i]值
if(a[j] > 0) t1 +=a[j];//t1往后添加一个a[i]值
else t2 +=-a[j];//t2往后添加一个a[i]值
ans = min(ans,max(t1,t2));//每次找出最小值赋给ans
}
printf("%I64d\n",ans);
}
}
return 0;
}