CF1661D Progressions Covering 题解

CF1661D Progressions Covering 题解

比较套路的贪心,与之类似的题不少。本篇题解不需要差分。

解法

显然,对这些选定区间的操作顺序不影响答案且没有后效性,所以考虑贪心。

这里选择从后向前贪心。对于位置 i i i,有如图的不超过 k k k 种区间对 a i a_i ai 有影响,且下面的区间对答案的贡献是严格优于上面的区间对答案的贡献的。值得注意的是每种区间可能不止 1 1 1 个。

img

注意到每个区间都是对 k k k 个位置有影响的,因为我们从后向前贪心,所以对于位置 i i i,对以 i i i 结尾的长度为 k k k 的区间需要几个有影响的区间是以 i + 1 i + 1 i+1 结尾到 以 i + k − 1 i + k - 1 i+k1 结尾的长度为 k k k 的区间。我们统计这些区间的个数和,方法类似于滑动窗口。

统计每种以 i i i 结尾的长度为 k k k 的区间有多少个,最后累加即可获得答案。

代码

#include<bits/stdc++.h>
using namespace std;
namespace fast_IO
{
	/*
	fast Input/Output
	*/
};
using namespace fast_IO;
#define int long long
int n,k,a[300010],ans,num[300010],sum,in;
signed main()
{
	read(n),read(k);
	for(int i=1;i<=n;i++) read(a[i]);
	for(int i=n;i-k+1>=1;i--)
	{
		if(a[i]>sum) num[i]=ceil((a[i]-sum)*1.0/k),sum+=num[i]*k,in+=num[i];
		sum-=in;
		if(i+k-1<=n) in-=num[i+k-1];
	}
	for(int i=k-1,delta;i;i--)
	{
		if(a[i]>sum) delta=ceil((a[i]-sum)*1.0/i),sum+=delta*i,in+=delta,num[k]+=delta;
		sum-=in;
		if(i+k-1<=n) in-=num[i+k-1];
	}
	for(int i=1;i<=n;i++) ans+=num[i];
	cout<<ans;
	return 0;
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值