ACwing算法备战蓝桥杯——day1——前缀和

前缀和分为一维前缀和与二维前缀和

一维前缀和就是前n项和,通过前缀和的减法可以求出一段区间的值:

实用技巧:1.s[i]+=s[i-1] 
        2.下标从1开始
        3.输入与预处理同时进行   
常用公式:s[i]+=s[i-1];
       a数组储存原始数据,s储存a的前n项和;
       上面这个公式是经过s[i]=s[i-1]+a[i]变形后得到的,在实际中最为常用;
       因为出现了i-1所以下标从1开始省去处理边界,大部分题目都以i=1开始最为实用;
       经过极简处理可用s数组储存数据,并且在数据输入阶段就进行前缀和的预处理,例如:
        const int N=1e5+10;            
        int n;
        int s[N];
        for(int i=1;i<=n;i++){
            scanf("%d",&s[i]);
            s[i]+=s[i-1];
        }

二维前缀和就是当前点与原点围成的矩形的数据之和;

常用公式:
有一个矩阵a[n][m](下标从1开始),以一对整数i,j,确定其前缀和以二维数组s[n][m]储存,既左上角的部分
    s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j]
由点(x1,y1),点(x2,y2)围成的矩形
    s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1]

今日份刷题:截断数组,前缀和,子矩阵和,激光炸弹,区域和检索,数组的中心下标,前缀和序列。

其中截断数组做蒙了,其他的感觉都只是简单的应用。

截断数组:

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

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

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

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

输入格式
第一行包含整数 n。

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

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

数据范围
前六个测试点满足 1≤n≤10。
所有测试点满足 1≤n≤1e5,−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

代码:
#include <iostream>
using namespace std;
const int N=1e5+10;
typedef long long LL;
int n,s[N];
int main(){
    cin>>n;
    if(n<3){
        puts("0");
        return 0;
    }
    for(int i=1;i<=n;i++){
        scanf("%d",&s[i]);
        s[i]+=s[i-1];
    }
    int sum=s[n];
    if(sum%3){
        puts("0");
        return 0;
    }
    LL res=0;//如果有1e5个0,组合个数可能会爆int
    int cnt=0;//记录前i个前缀和满足s[n]/3的个数;
    for(int i=1;i<=n-2;i++){//两刀构成一种切法,注意有负数;
        if(s[i]==sum/3) cnt++;//前i前缀和,满足第一刀的切法
        if(sum-s[i+1]==sum/3) res+=cnt;//当满足一次第二刀切法时,与第一刀的切法构成cnt种切法
    }
    cout<<res<<endl;
    return 0;
}    

题解:

首先要对总合进行特判,如果不满足是3的倍数,就直接排除;

关键点为代码61行,用cnt记录枚举过的数据中每个前缀和满足s[n]/3的次数,也就是第一段;

代码62行寻找第三段满足s[n]/3的点 ( 当第三段和第一段都满足时,中间一段自然满足s[n]/3 ),

此时如果发现有满足第三段i的位置,就与第一段的cnt种情况相匹配;

易错点:

1.数据有负数;

2.数据范围,假设全部数据都为当前数据可达到的最大值1e4,数据总量为1e5,所以最后一个前缀 和为1e9,又int的最大值为1e9,所以会"爆int",需设置成long long即可;

前缀和总结:主要是在数据范围与内存上出错,容易溢出与超出内存。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

切勿踌躇不前

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

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

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

打赏作者

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

抵扣说明:

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

余额充值