【算法】前缀和
目录
🍔前缀和:
🍔模板
🍔应用
🎆音乐分享(点击链接可以听哦)
A Hundred Miles(一百英里) - Meat Puppets - 单曲 - 网易云音乐 (163.com)
前缀和:
什么是前缀和:
原数组: a[1], a[2], a[3], a[4], a[5], …, a[n]
前缀和 Si为数组的前 i项和
前缀和: S[i] = a[1] + a[2] + a[3] + … + a[i]
求 [l, r]中的和, 即为 S[r] - S[l-1]
前缀和的作用:
快速求出元素组中某段区间的和
方法:
首先做一个预处理,定义一个sum[]数组,sum[i]代表a数组中前i个数的和
for(int i = 1; i <= n;i++)
{
sum[i] = sum[i - 1] + a[i];
}
这样,对于每个询问,只需要执行 sum[r]-sum[l-1]。输出原序列中从第l个数到第r个数的和的时间复杂度变成了O(1)。
注意:
下标最好从1开始(从0开始也可以,主要是根据个人习惯)
🚥🚥🚥🚥🚥🚥
模板
795. 前缀和 - AcWing题库
输入一个长度为 n 的整数序列。
接下来再输入 m 个询问,每个询问输入一对 l,r。
对于每个询问,输出原序列中从第 l 个数到第 r 个数的和。
输入格式
第一行包含两个整数 n 和 m。
第二行包含 n 个整数,表示整数数列。
接下来 m 行,每行包含两个整数 l 和 r,表示一个询问的区间范围。
输出格式
共 m 行,每行输出一个询问的结果。
代码
#include <iostream>
using namespace std;
const int N = 100010;
int n, m;
int a[N], s[N];
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i ++ ) scanf("%d", &a[i]);
for (int i = 1; i <= n; i ++ ) s[i] = s[i - 1] + a[i]; // 前缀和的初始化
while (m -- )
{
int l, r;
scanf("%d%d", &l, &r);
printf("%d\n", s[r] - s[l - 1]); // 区间和的计算
}
return 0;
}
⭐⭐⭐⭐⭐⭐
应用
Problem - D - Codeforces
嘿嘿嘿,CF虐我千百遍,我待CF如初见! (doge)
🏳️🌈🏳️🌈🏳️🌈
小吉是真的没有想到这道题可以用前缀和来写(学了前缀和,但是没有发挥用途,我真的会乌鱼呀,让我怎么荔枝呀(纯纯坤语言doge))
🏳️🌈🏳️🌈🏳️🌈
这道题依然传承了cf的基本格式( t 个样例,然后进行讨论)
cf的题,都会给出样例,如果题目描述中有样例解释,一定要看,因为有时候题目看不懂(呜呜呜,因为是英语),但是看样例却可以看懂,甚至可以做对题
题目含义:
总个数 n
题目中给出了 l r k 三个字母,其中,l 可以代表左边界的下标,r 可以代表右边界的下标,
(l - r + 1)代表需要替换的长度,这个长度中的每个数的大小是 k
(比如 l=2 r=3 k=3,那么长度为2,为 [ 3 , 3] )
情况1:替换的长度(l - k + 1) = n
那么所有的数(n个数)的值都为k
情况2:替换的长度(l - k + 1) < n
由于替换的长度(l - k + 1) < n,那么就要用原数组的数来补全没有被替换掉的数
这个时候,我们应该如何在原数组里面对应被替换掉的数的位置和数组中剩下的数的位置和大小呢,这就要用到前缀和了
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
ll a[N],sum[N];
int main(){
int t;
cin>>t;
while(t--){
int n,q;
cin>>n>>q;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;i++)sum[i]=sum[i-1]+a[i];//前缀和
while(q--){
int l,r,k;
cin>>l>>r>>k;
ll ans=sum[n]-(sum[r]-sum[l-1])+(r-l+1)*k;
if(ans%2==0)cout<<"NO"<<endl;
else cout<<"YES"<<endl;
}
}
}
Code over!