【算法合集】前缀和与差分

✅🎡个人主页:程序猿追

✅🎡系列专栏:算法合集

✅🎡目前状态:创建Java学习之路(零基础到就业实战)系列,目前更新到JAVAWEB开发

✅🎡作者简介:大家好,我是程序猿追,全栈领域新星创作者,算法爱好者,常在作者周榜排名前30,某不知名的 ACMer

✅🎡推荐一款刷题面试找工作三不误的网站——牛客网

✅🎡个人名言:不积跬步无以至千里,趁年轻,使劲拼,给未来的自己一个交代!

目录

一、前缀和

1、一维前缀和

2、二维前缀和

二、差分

1、一维差分

2、二维差分


一、前缀和

1、一维前缀和

啥是前缀和?

字面意思前面数到后面数的和(又叫区间和),假设我们有一组数组[1,2,3,4,5],输入左区间与右区间,这区间它们两的和(不是下标哟)。

例子

数组长度为 6 ,元素是[1,2,3,4,5,6],区间 1 到 3 的和是6,这样的就叫一维前缀和。

直接看代码

#include <bits/stdc++.h>

using namespace std;

const int N = 100000 + 10;

int n, m;
int arr[N], srr[N];

int main()
{
    cin >> n >> m;
    for (int i = 1; i <= n; i ++ ) cin >> arr[i];

    for (int i = 1; i <= n; i ++ ) srr[i] = srr[i - 1] + arr[i];

    while (m -- )
    {
        int l, r;
        cin >> l >> r;
        cout << srr[r] - srr[l - 1] << endl;
    }

    return 0;
}

n 是数组的长度,m 是要操作的次数,l 是左区间,r是右区间

2、二维前缀和

 啥是二维前缀和?

我们直接看图

假设 a 是个大区间的我们要求 d 区间的数据和,先求 f 的和再减去两个 b 区间的和,b 区间明显多减了一次,所以左后面再加上 c 区间。

假设有一个长度为 5 宽度为 3 的一个数组,里面都是1,2,3数据,坐标(1,1)到(2,2)的和明显是 1 + 2 + 1 + 2。

#include <bits/stdc++.h>

using namespace std;

const int N = 1000 + 10;

int n, m, q;
int arr[N][N], srr[N][N];

int main()
{
    cin >> n >> m >> q;

    for (int i = 1; i <= n; i ++ )
        for (int j = 1; j <= m; j ++ )
            cin >> arr[i][j];

    for (int i = 1; i <= n; i ++ )
        for (int j = 1; j <= m; j ++ )
            srr[i][j] = arr[i][j] + srr[i - 1][j] + srr[i][j - 1] - srr[i - 1][j - 1];

    while (q --)
    {
        int x1, y1, x2, y2;
        cin >> x1 >> y1 >> x2 >> y2;
        cout << srr[x2][y2] - srr[x2][y1 - 1] - srr[x1 - 1][y2] + srr[x1 - 1][y1 - 1] << endl;
    }

    return 0;
}

二、差分

1、一维差分

通过上面我们知道了,什么是前缀和,那么什么是差分呢?就是在一区间减去某一个数或加上某一个数,假如 1 到 3 区间有1,2,3 三个数据,对它进行 + 1 与 - 2操作,再来求它的和,这就是典型的差分。

#include <bits/stdc++.h>

using namespace std;

const int N = 100000 + 10;

int n, m, arr[N], srr[N];

int main()
{
    cin >> n >> m;
    for(int i = 1; i <= n; i ++)
    {
        cin >> arr[i];
        srr[i] += arr[i];
        srr[i + 1] -= arr[i];
    }

    while(m --)
    {
        int l, r, c;
        cin >> l >> r >> c;
        srr[l] += c;
        srr[r + 1] -= c;
    }
    for(int i = 1; i <= n; i ++)
    {
        srr[i] += srr[i - 1];
        cout << srr[i] << ' ';
    }
}


2、二维差分

同样的道理这里就不多说了。

#include <bits/stdc++.h>

using namespace std;

const int N = 1010;

int n, m, q;
int arr[N][N], srr[N][N];

int main()
{
    cin >> n >> m >> q;
    for (int i = 1; i <= n; i ++ )
        for (int j = 1; j <= m; j ++ )
            scanf("%d", &srr[i][j]);

    for (int i = 1; i <= n; i ++ )
        for (int j = 1; j <= m; j ++ )
            arr[i][j] = srr[i][j] - srr[i - 1][j] - srr[i][j - 1] + srr[i - 1][j - 1];

    while (q --)
    {
        int x1, y1, x2, y2, c;
        scanf("%d%d%d%d%d", &x1, &y1, &x2, &y2, &c);
        arr[x1][y1] += c;
        arr[x1][y2 + 1] -= c;
        arr[x2 + 1][y1] -= c;
        arr[x2 + 1][y2 + 1] += c;
    }

    for (int i = 1; i <= n; i ++ )
        for (int j = 1; j <= m; j ++ )
            srr[i][j] = arr[i][j] + srr[i - 1][j] + srr[i][j - 1] - srr[i - 1][j - 1];

    for (int i = 1; i <= n; i ++ )
    {
        for (int j = 1; j <= m; j ++ ) printf("%d ", srr[i][j]);
        cout << endl;
    }

    return 0;
}


 算法对程序员来说及其重要,语言和开发平台不断变化,但是万变不离其宗的是那些算法和理论,依稀记得我那个玩的很好的一个学长(在大二就拿到了 offer),他告诉我想找一个好的工作,那刷题一定是必不可少的

现在算法刷题平台还是蛮多的,给大家介绍一个我认为与大厂关联最深的平台——牛客网

  • 52
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 48
    评论
评论 48
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

程序猿追

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

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

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

打赏作者

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

抵扣说明:

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

余额充值