算法——前缀和及差分

前缀和及差分

​ 前缀和与差分是互为逆运算的两种计算方式,前缀和指的是一个数组是另一个数组中前n项元素之和,而差分指的是一个数组的前n项的和是另一个数组

​ 实际上就是,如果数组a是数组b的前缀和,那b就是a的差分

前缀和

​ 根据如上的的解释,我们可以理解为,假设有数组a[1, 2, 3, 4, 5]那么代表它的前缀和数组的数组b就是1, 3, 6, 10, 15,也就是说,a[n] = b[1] + b[2] + ... + b[n - 1] + b[n],这里我们假设数组是从下标1开始的,这样我们可以减去一步繁琐的判断

​ 通过前缀和,我们可以快速的求出原数组从lr的区间中元素的和,等于S[l ~ r] = b[r] - b[l - 1],有如下代码:

代码

#include <iostream>

using namespace std;

const int N = 1e5 + 1;

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, r;
        scanf("%d%d", &l, &r);
        printf("%d\n", s[r] - s[l - 1]);
    }
}

差分

​ 作为前缀和的逆运算,差分可以理解为有算数组a,它的差分数组b有如下关系

a[1] = b[1]
a[2] = b[1] + b[2]
a[3] = b[1] + b[2] + b[3]
...
a[n - 1] = b[1] + b[2] + b[3] + ... + b[n - 2] + b[n - 1]
a[n] = b[1] + b[2] + b[3] + ... + b[n - 2] + b[n - 1] + b[n]

​ 由此可见,如果ba的差分数组,那a就是b的前缀和数组,通过差分,我们可以快速的实现对一个区间内的所有元素的同增同减操作

​ 假设我们要让a[2]a[6]的元素全部+1,我们只需要让b[2] += 1b[7] -= 1即可,代码如下

代码

#include <iostream>

using namespace std;

const int N = 100010;

int a[N], b[N];

int n, m;

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++) b[i] = a[i] - a[i - 1];
    while (m--) {
        int l, r, c;
        scanf("%d%d%d", &l, &r, &c);
        b[l] += c;
        b[r + 1] -= c;
    }
    for (int i = 1; i <= n; ++i) {
        a[i] = a[i - 1] + b[i];
        printf("%d ", a[i]);
    }
}
发布了72 篇原创文章 · 获赞 89 · 访问量 6517

猜你喜欢

转载自blog.csdn.net/scfor333/article/details/105051559
今日推荐