算法【一维前缀和】

🌹作者:云小逸
📝个人主页:云小逸的主页
📝Github:云小逸的Github
🤟motto:要敢于一个人默默的面对自己,强大自己才是核心。不要等到什么都没有了,才下定决心去做。种一颗树,最好的时间是十年前,其次就是现在!学会自己和解,与过去和解,努力爱自己。==希望春天来之前,我们一起面朝大海,春暖花开!==🤟
👏专栏:C++👏 👏专栏:Java语言👏
👏专栏:C语言初阶👏👏专栏:数据结构👏


前言

今天这篇文章是备战蓝桥杯的第五篇文章,这一篇文章是写的是一维前缀和和二维前缀和的相关算法问题,如有错误,请私信并告知,十分感谢!!!
———————————————————————————————————————————

前缀和:

什么是前缀和

前缀和指一个数组的某下标之前的所有数组元素的和(包含其自身)。前缀和分为一维前缀和,以及二维前缀和。前缀和是一种重要的预处理,能够降低算法的时间复杂度。
例如:
数组: a[1], a[2], a[3], a[4], a[5], …, a[n] 下标从1开始
前缀和: S[i] = a[1] + a[2] + a[3] + … + a[i]包含其自身

这里的下标从1开始,这样便于理解,不用进行下标的转换,省着在做题的时候,容易把自己绕糊涂。

s[0] = 0
s[1] = a[1]
s[2] = a[1] + a[2]

题目:

输入一个长度为 n 的整数序列。接下来再输入 m 个询问,每个询问输入一对 l,r。

对于每个询问,输出原序列中从第 l 个数到第 r 个数的和。

输入格式

第一行包含两个整数 n 和 m。

第二行包含 n 个整数,表示整数数列。

接下来 m 行,每行包含两个整数 l 和 r,表示一个询问的区间范围。

输出格式

共 m 行,每行输出一个询问的结果。

数据范围

1≤l≤r≤n,
1≤n,m≤100000,
−1000≤数列中元素的值≤1000​

输入样例:

5 3
2 1 3 6 4
1 2
1 3
2 4

输出样例:

3
6
10

做题思路:

使用一个预处理数组s来存储从a[1]到a[i]的和,然后使用s[r]-s[l-1]来计算从a[l]到a[r]的和。

代码:

#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=0,r=0;
        scanf("%d%d",&l,&r);
        printf("%d\n",s[r]-s[l-1]);//这里要注意区间间的运算
    }

    return 0;
}

截断数组

题目:

给定一个长度为 n 的数组 a1,a2,…,an。

现在,要将该数组从中间截断,得到三个非空子数组。

要求,三个子数组内各元素之和都相等。

请问,共有多少种不同的截断方法?

输入格式

第一行包含整数 n。

第二行包含 n 个整数 a1,a2,…,an。

输出格式

输出一个整数,表示截断方法数量。

数据范围

前六个测试点满足 1≤n≤10。
所有测试点满足 1≤n≤105,−10000≤ai≤10000。

输入样例1:

4
1 2 3 3

输出样例1:

1

输入样例2:

5
1 2 3 4 5

输出样例2:

0

输入样例3:

2
0 0

输出样例3:

0

解题思路:

解题思路是使用前缀和来求解。首先,通过输入n个数,构建一个前缀和数组s,其中s[i]表示前i个数的和。然后,判断s[n]是否能被3整除,如果不能,则输出0,表示无解。如果能,则遍历s数组,计算s[i-2]和s[n]-s[i-1]是否等于s[n]/3,如果相等,则表示存在一个子数组,其和为s[n]/3,最后输出符合条件的子数组的个数。

代码:

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

const int N=100010;
int n=0;
int s[N];

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&s[i]);
        s[i]+=s[i-1];
    }
    
    if(s[n]%3)
    {
        puts("0");
        return 0;
    }
    
    long long res=0;
    for(int i=3,cnt=0;i<=n;i++)
    {
        if(s[i-2]==s[n]/3) cnt++;
        if(s[n]-s[i-1]==s[n]/3) res+=cnt;
    }
    
    printf("%lld",res);
    return 0;
}

在这里插入图片描述


最后

十分感谢你可以耐着性子把它读完和我可以坚持写到这里,送几句话,对你,也对我:

1.当你的能力不能取代的时候,你自身的弱点才有可能被人忽视。

2.请你擦亮自己的眼睛,看清楚这个现实的社会,有用的时候,你在别人的手中就是一块宝,没有用的时候,你在别人的手中就是垃圾,随处可扔。

3你身边一定有不少这样的人,平时看起来人畜无害,遇到事的时候,就先给你捅刀子。

4.这人一走,茶也跟着凉,这是自然规律,这人还没走,茶还跟着凉,这是世态炎凉。

5.不要以为别人事事都拿你当回事,其实,你在他们眼里,你只配给他们舔鞋。

最后如果觉得我写的还不错,请不要忘记点赞✌,收藏✌,加关注✌哦(。・ω・。)

愿我们一起加油,奔向更美好的未来,愿我们从懵懵懂懂的一枚菜鸟逐渐成为大佬。加油,为自己点赞!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

云小逸

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

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

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

打赏作者

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

抵扣说明:

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

余额充值