2021牛客寒假算法基础集训营5_D_石子游戏(贪心+差分)

题目

在这里插入图片描述

分析

图中每列代表一堆石子,高度代表石子数量,k=3
在这里插入图片描述
如何遍历?

  1. 最终高度是多少?有可能很高,因此,即便知道一个加石子的方案,一次一次地加,也是复杂度太高。
  2. 往k个石子堆添加一块石子时,称最左边的堆所在的位置为添加起点。显然,按添加起点可将所有添加石子的动作分为n-k+1类,则遍历这些分类可行
  3. 从左向右遍历分类,则贪心成立。贪心策略: 先将最左边的一次性加到目标高度,然后是左边的第二个位置,依次类推。
  4. 那么目标高度是多少?
  5. 初始的高度目标可以设为初始的最大值,在从左往右的添加过程中,若出现了更大的高度,则更新目标高度
  6. 新的高度出现后,应立即使得左侧已达到原有目标高度的达到新高度,若成功则继续,否则失败结束。
  7. 添加石子是区间操作,因此采用差分数组维护数据。
    在这里插入图片描述

代码

#include<bits/stdc++.h>
using namespace std;
#define MAXN  100010
long long ans, mx, dh[MAXN], delt;
int T, a[MAXN], n, k;
int main(){
    scanf("%d", &T);
    while(T--){
        scanf("%d %d", &n, &k), mx = 0, ans = 0;
        for(int i = 1; i <= n; i++)
            scanf("%d", a+i), mx = max(mx, (long long)a[i]);
        memset(dh, 0, sizeof dh);
        for(int i = 1; i <= n; i++){
            dh[i] += dh[i-1];
            if(dh[i] + a[i] > mx) {
                if((i-1)%k != 0) {
                    ans = -1;
                    break;
                }
                ans += (i-1) / k *(dh[i]+a[i] - mx);
                mx = dh[i] + a[i];
            }
            else if(dh[i] + a[i] < mx){
                if(i+k > n+1){
                    ans = -1;
                    break;
                }
                delt = mx - dh[i] - a[i];
                dh[i] += delt, dh[i+k] -= delt;
                ans += delt;
            }
        }
        printf("%lld\n", ans);
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jpphy0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值