[AT_past202104_d] K項足し算 题解

题目传送门 \color{orangered}\text{题目传送门} 题目传送门

题意

有一个长度为 n n n 的数列,数列中第 i i i 个数被记为 a i a_i ai 1 ≤ i ≤ n 1≤i≤n 1in )。

给定一个 k k k ,请按照 i = 1 , 2 , . . . , n − k + 1 i=1,2,...,n-k+1 i=1,2,...,nk+1 的顺序计算 a i + a i + 1 + . . . + a i + k − 1 a_i+a_{i+1}+...+a_{i+k-1} ai+ai+1+...+ai+k1 的结果并输出。

分析

这道题最直观的做法是直接按题目模拟,用双重循环来做,主要代码见下:

llrd(n);llrd(k);
for(int i=1;i<=n;i++) llrd(a[i]);
for(int i=1;i<=n-k+1;i++)
{
	ll ans=0;
	for(int j=i;j<=i+k-1;j++) ans+=a[j];
	llwt(ans);
}

可是我们发现数据范围是 1 ≤ K ≤ N ≤ 5 × 1 0 5 1\le K \le N \le 5\times 10^5 1KN5×105,所以双重循环会超时,不能用双重循环来做。


正解:前缀和做法。

不知道前缀和的同学可以看一下这篇文章

我们用 s u m i sum_i sumi 来表示从第 1 1 1 项到第 i i i 项的和,所以第 a a a 项到第 b b b 项的和就是 s u m b − s u m a − 1 sum_b-sum_{a-1} sumbsuma1

枚举每个 i i i,输出 s u m i + k − 1 − s u m i − 1 sum_{i+k-1}-sum_{i-1} sumi+k1sumi1 即可,记得换行。

完整代码见下。

代码

#include<bits/stdc++.h>
#define rd(n) scanf("%d",&n)
#define llrd(n) scanf("%lld",&n)
#define wt(n) printf("%d",n)
#define llwt(n) printf("%lld\n",n)
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define ll long long
using namespace std;
ll n,k;
ll a[500100],sum[500100];
int main()
{
	llrd(n);llrd(k);
	for(int i=1;i<=n;i++)
	{
		llrd(a[i]);
		sum[i]=sum[i-1]+a[i];
	}
	for(int i=1;i<=n-k+1;i++) llwt(sum[i+k-1]-sum[i-1]);
   	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值