2021牛客寒假算法基础集训营5 D.石子游戏(差分)

D.石子游戏

题目链接:https://ac.nowcoder.com/acm/contest/9985/D

题目描述:

叶妹妹很喜欢玩石头,于是这天泽鸽鸽给她出了一道石子游戏,规则是这样的:有n堆石子排成一行,其中第i堆石子有ai个,叶妹妹可以选择做无数次这种操作:每次操作把连续相邻的k个石子堆中的每堆石子数目加一,请问叶妹妹能否让每堆石子的数目都相同呢?叶妹妹觉得这题太简单了,于是丢给了聪明的你,快来解决这个问题吧!

输入描述:

第一行输入样例组数T

对于每组样例来说,第一行输入两个数n和k

第二行输入n个数,其中第i个数为ai

【数据规模与约定】

1≤T≤10,1≤n≤10^5 ,1≤k≤n,0≤ai≤10^9

输出描述:

输出总共T行,对于每组样例来说,如果能使每堆石子的数目都相同则输出一个整数x,x表示达到相同时的最少的操作数;否则输出-1

示例1:

输入
1
4 3
1 1 1 2
输出
1

解题思路:

差分
从后向前进行操作,如果找到了任意的x>0,则用x次操作变为0。对于本题来说,给一个后缀+1,(第n+1-k个位置+1)会受到影响,(也就是n+1%k同余位置),因此需要把这些位置的负数置0。

代码如下:

#include<iostream>
#include<cstdio>
using namespace std;
#define ll long long
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		int n,k,a[100010]={0};
		scanf("%d%d",&n,&k);
		for(int i=1;i<=n;i++){
			scanf("%d",&a[i]);
		}
		for(int i=n;i>=1;i--){
			a[i]-=a[i-1];  //求差分数组
		}
		ll ans=0;
		for(int i=n;i>=2;i--)
			if(i>k&&a[i]>0) 
				ans+=a[i],a[i-k]+=a[i],a[i]=0;
		int t=1;
		for(int i=2;i<=n;i++){
			if(a[i]<0&&(i%k==(n+1)%k))
				ans-=(n+1-i)/k*(ll)a[i],a[i]=0;  //特判
			t&=!a[i];
		}
		if(!t) ans=-1;
		printf("%lld\n",ans);
	}
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值