https://ac.nowcoder.com/acm/contest/9985/D
题意:
叶妹妹很喜欢玩石头,于是这天泽鸽鸽给她出了一道石子游戏,规则是这样的:有n堆石子排成一行,其中第i堆石子有ai个,叶妹妹可以选择做无数次这种操作:每次操作把连续相邻的k个石子堆中的每堆石子数目加一,请问叶妹妹能否让每堆石子的数目都相同呢?叶妹妹觉得这题太简单了,于是丢给了聪明的你,快来解决这个问题吧!
思路:
一眼的差分题阿。但是边界搞糊涂了。再理解理解。
差分就是表示每个数之间的差。那么对于此题就是要求我们使得cnt[i]=a[i+1]-a[i],也就是使得n-1个差分数组都为0.
只要都为0就可以了,所以cnt[n]和cnt[0]是多少无所谓,而cnt[n]和cnt[0]是多少其实影响的是最后序列里的每个数是多少,不影响相等不相等。
于是前往后扫一遍,由于是区间+1,所以只对cnt[i]<0的进行操作。注意边界是i+k>n,而不是=n,因为最后一个数cnt[n]和cnt[0]是无所谓的。
然后后往前扫一遍,此时是反过来的。cnt[i]>0的话说明后面的大,要给前面的数都加,于是cnt[i-k]+=abs(cnt[i])
#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=1e5+1000;
typedef long long LL;
inline LL read(){LL x=0,f=1;char ch=getchar(); while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;}
LL a[maxn],cnt[maxn];
int main(void)
{
cin.tie(0);std::ios::sync_with_stdio(false);
LL t;cin>>t;
while(t--){
LL n,k;cin>>n>>k;
for(LL i=1;i<=n;i++) cin>>a[i],cnt[i]=0,cnt[0]=cnt[n+1]=0;
for(LL i=1;i<n;i++){
cnt[i]=(a[i+1]-a[i]);
}
LL ans=0;
for(LL i=1;i<n;i++){
if(cnt[i]<0){
if(i+k>n) continue;
cnt[i+k]-=abs(cnt[i]);
ans+=abs(cnt[i]);
cnt[i]=0;
}
}
for(LL i=n-1;i>=1;i--){
if(cnt[i]>0){
if(i-k<0) continue;
cnt[i-k]+=abs(cnt[i]);
ans+=abs(cnt[i]);
cnt[i]=0;
}
}
bool flag=1;
for(LL i=1;i<n;i++){
if(cnt[i]!=0){
cout<<"-1"<<"\n";
flag=0;break;
}
}
if(1==flag){
cout<<ans<<"\n";
}
}
return 0;
}