【蓝桥杯C/C++组】备赛基础篇之差分算法

一、个人理解

前面学习了前缀和算法,对于访问任意区间的速度是比较快的,但如果我们要修改某个区间的数呢,对于前缀和算法来说这还是有点棘手。

所以我们来学学新的算法:差分算法!

前缀和数组储存的是前n个数的和,而差分代表的是与前一个的差值。

 

 为什么要这么储存呢???

因为这么储存之后,我们就可以对我们的原数组进行修改,假如我们在第 l 个位置加上一个值,就会影响后面所有的数值 ,这时候我们只需要在我我们要截止的地方后面一个数(也就是r+1)加上一个数值就可以了(后面的正负相抵没有了)。这样,就只用修改两处就让我们想要修改的区间全部修改好了。

我们该如何得到我们的值呢?

想必大家都学过数学的累加,既然存的是差值,我每一个都相加不就是我们要的答案吗??

 

 为了防止越界,标记数组的索引从1开始。x0 = 0.

二、详细代码

#include<iostream>

using namespace std;

const int N = 100000 + 10;
int a[N], n, m;//a数组表示的是与前一个数的差值。

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

int main() {
    int x;
    scanf("%d%d", &n, &m);
    for (int i = 1;i <= n;i++) scanf("%d", &x), insert(i, i, x);

    while (m--) {
        int l, r, c;
        scanf("%d%d%d", &l, &r, &c);
        insert(l, r, c);
    }

    for (int i = 1;i <= n;i++) {
        a[i] += a[i - 1];
        printf("%d ", a[i]);
    }
    return 0;
}

三、升级---->差分矩阵

 

#include<iostream>
#include<cstdio>
using namespace std;

const int N = 1010;
int a[N][N];

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

int main() {
    int n, m, q, x1, y1, x2, y2, c;
    scanf("%d%d%d", &n, &m, &q);

    for (int i = 1;i <= n;i++)
        for (int j = 1; j <= m; j++)
            scanf("%d", &c), insert(i, j, i, j, c);

    while (q--) {
        scanf("%d%d%d%d%d", &x1, &y1, &x2, &y2, &c);
        insert(x1, y1, x2, y2, c);
    }

    for (int i = 1;i <= n; i++) {
        for (int j = 1;j <= m; j++) {
            a[i][j] += a[i - 1][j] + a[i][j - 1] - a[i - 1][j - 1];
            printf("%d ", a[i][j]);
        }
        printf("\n");
    }
    return 0;
}

 

posted @ 2020-05-21 15:40  Vincent&  阅读(498)  评论(0编辑  收藏  举报