详解一维差分

一维差分

前缀和和差分互为逆运算

还是用高中的数列的知识: 可以把 差分 理解为 已知**前N项和Sn 求an **

b[i] += b[i - 1]:a[]是b[]的前缀和

做以下的举例:

b = {0,1,3,7,12,8}//因为此算法中的数组都是从1开始初始化的,所以0号位默认是0

a[0] = 0; a[1] = 1; a[2] = 4; a[3] = 11; a[4] = 23; a[5] = 31;

当进行insert(1,3,10)时,分两步进行:

① : b[l] += c : b[1] += 10

​ a[0] = 0; a[1] = 11; a[2] = 14; a[3] = 21; a[4] = 33; a[5] = 41;

②: b[r + 1] -= c : b[3 + 1] -=10

​ a[0] = 0; a[1] = 11; a[2] = 14; a[3] = 21; a[4] = 23; a[5] = 31;

得到正确答案

总结一下:当an 进行了 +C 操作时, 后面的(包括n) Sn 肯定也会跟着进行 +C操作;但我们要的只是区间[n,m]进行+C 操作,所以 还要在am+1 进行 -C 操作(加减抵消),即可保证变化的只是区间[n,m]

一维差分

输入一个长度为 n 的整数序列。

接下来输入 m 个操作,每个操作包含三个整数 l,r,c,表示将序列中 [l,r] 之间的每个数加上 c

请你输出进行完所有操作后的序列。

#include<bits/stdc++.h>

const int N = 1010;
int a[N],b[N];  //若是看成高中的数列知识,a就是Sn,b就是an;

void insert(int l, int r, int c)
{
    b[l] += c;//第一次insert(a[i])时,是初始化b[i];第二次insert(c)是,是计算区间和的操作
    b[r + 1] -= c;
}

int main()
{
    int n,m;
    scanf("%d%d",&n,&m);//确定序列长度和查询次数
    
    for(int i = 1; i <= n; i ++) scanf("%d",&a[i]);  //a[]是b[]的前缀和
    
    for(int i = 1; i <= n; i ++) insert(i,i,a[i]);//初始化b[i]操作
    
    while(m --)
    {
        int l,r,c;
        scanf("%d%d%d",&l,&r,&c);//把区间[l,r]中的数值统一进行+c的操作
        insert(l,r,c);
    }
    
    for(int i = 1; i <= n; i ++) b[i] += b[i - 1];
    
    for(int i = 1; i <= n; i ++) printf("%d ",b[i]);
    
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Nmj_World/article/details/125861152
今日推荐