一维差分
前缀和和差分互为逆运算
还是用高中的数列的知识: 可以把 差分 理解为 已知**前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;
}