前缀和 蒜头君班级排队打水

题目是这样的:
在这里插入图片描述
Sample Input

5
1 3 5 4 2
2
1 3
2 5

Sample Output

51

这道题如果不考虑时间的话很容易解,但最后会超时。
所以这道题的关键就在于如何用一层循环解决。

解决思路如下:

首先这道题在草稿纸上演算,拿输入样例来说,如果要知道某个区间打水的人花费的时间总和,可以先不看特定区间,先算出每个人打水需要的时间,我们把每个人打水需要的时间存到一个新的数组里,命名为b[n]
也就是

a[n] 1 3 5 4 2

b[n] 1 4 9 13 15

于是每个人打水需要的时间就有啦,他问时间和,假如说我们要的区间就是从第1个人到第n个人,也就是每次都是从第一个人开始的,如果是这种情况,我们则需要b1+b2+…+bn

如果两次循环不超时那分析到这里就已经没问题了,关键是如何不用双重循环来实现一个区间的加和呢。我们只能用一重循环的话,本来自闭了很久觉得impossible,但想了想没有什么是再加一个数组或者结合数学列个式子不能解决的了(误

于是我们还按照那个从1到n取区间走起,我们目的是求和b1+b2+…+bn ,那我们再来加个数组 c[n] c[i]是b[1]到b[i] 的加和
于是乎是酱紫

a[n] 1 3 5 4 2
b[n] 1 4 9 13 15
c[n] 1 5 14 28 43

也就是前缀和的前缀和

嗯…这个出来了,之后就是想如何实现任意区间,那不就用第三个数组做个减法的事嘛,其实题目中已经给提示了,取一个连续区间。因为用一重循环所以必须做到给出l,r就能算出结果,那就必须要写一个式子! 所以草稿纸上演算一下,不难得出

sum += (c[r]-c[l-1]-b[l-1]*(r-l+1))%1000000007;

于是肯定会想为啥要再取余一下(在这里没考虑过,于是卡了一个小时)因为本来就是long long int,进行加法会爆掉的的的 所以记得在这里取余一下
好啦,上代码(注意long longi nt

#include<stdio.h>
long long int n,q,l,r,i,j;
long long int sum=0;
long long int a[100100]={0};
long long int b[100100]={0};
long long int c[100100]={0};
int main(){
	b[0]=0;
	c[0]=0;
	scanf("%d",&n);
	for(i=1;i<=n;i++){
		scanf("%d",&a[i]);
		b[i]=b[i-1]+a[i];
		c[i]=c[i-1]+b[i];
	}
	scanf("%d",&q);
	for(j=1;j<=q;j++){
		scanf("%d%d",&l,&r);
		sum += (c[r]-c[l-1]-b[l-1]*(r-l+1))%1000000007;

	}
	printf("%d",sum%1000000007);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值