前缀和 与 差分

前缀和:

有一个长度为n的数组:a1, a2, a3, … , an。
前缀和si = a1 + a2 + a3 + … + ai。
作用:快速求出数组某一个区间的和

同理,我们可以推广到二维、三维等等。
前缀和最主要的就是思维

求解

一维前缀和:
const int N = 1e5 + 10;
int a[N], s[N], t;
for (int i = 1; i <= n; i ++ )    cin >> a[i];//原数组
for (int i = 1; i <= n; i ++ )    s[i] = a[i] + s[i - 1];//前缀和数组

快速求出区间[ l, r]之间的和
cin >> l >> r;
cout << s[r] - s[l - 1] << endl;
二维前缀和:
const int N = 1e5 + 10;
int a[N], s[N];
for (int i = 1; i <= n; i ++ )
    for (int j = 1; j <= m; j ++ )
        cin >> a[i][j];//输入原数组
for (int i = 1; i <= n; i ++ )
    for (int j = 1; j <= m; j ++ )
        s[i][j] = a[i][j] + s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1];//前缀和数组

快速求出(x1, y1)(x2, y2)两点之间矩阵的和
s = s[x2][y2] - s[x2][y1 - 1] - s[x1 - 1][y2] + s[x1 - 1][y1 - 1];

差分:

本质:前缀和的逆运算

有一个长度为n的a数组:a1, a2, a3, … , an。
现在构造一个b数组:b1, b2, b3, … , bn。
使得a数组是b数组的一个前缀和数组,
即 ai = b1 + b2 + b3 + … + bi;
即a数组是b数组的前缀和,b数组是a数组的差分。

作用:用于对一个区间的数进行加减操作,将复杂度从O(n)降到O(1)。

例如:
将【l, r】 区间的每一个数都加上C;
利用差分数组,只需将b[l] + C, b[r + 1] - C。

一维差分数组:
#include <iostream>

using namespace std;

const int N = 1e5 + 10;
int a[N], b[N];

void insert (int l, int r, c)
{
    b[l] += c;
    b[r + 1] -= c;
}

int main ()
{
    for (int i = 1; i <= n; i ++ )   cin >> a[i];
    for (int i = 1; i <= n; i ++ )   insert(i, i, a[i]);//相当于在[i, i]区间每一个数加上a[i],构造差分数组
    //对[l,r]所有的数加上一个x
    while (cin >> l >> r >> x)   insert (l, r, x);
    for (int i = 1; i <= n; i ++ )    b[i] += b[i - 1];//求解操作后的a数组,即b的前缀和数组
    for (int i = 1; i <= n; i ++ )    cout << b[i] << " ";
    cout << endl;

    return 0;
}
二维差分数组:
#include <iostream>

using namespace std;

const int N = 1e5 + 10;
int n, m;
int a[N], b[N];

void insert (int x1, int y1, int x2, int y2, int x)
{
    b[x1][y1] += x;
    b[x1][y2 + 1] -= x;
    b[x2]
}

int main ()
{
    cin >> n >> m;
    for (int i = 1; i <= n; i ++ )
       for (int j = 1; j <= m; j ++ )
           cin >> a[i][j];//原数组
    
    for (int i = 1; i <= n; i ++ )
       for (int j = 1; j <= m; j ++ )
           insert (i, j, i, j, a[i]);
           //构造差分数组
    while (cin >> x1 >> y1 >> x2 >> y2 >> x)    insert (x1, y1, x2, y2, x);
       
}

二维差分数组未编完

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值