Acwing 797 差分

差分定义

 首先定义差分:前缀和的逆运算
 给定已知的数组 a i a_i ai,求数组 b i b_i bi。使得以下条件成立
b i = a i − a i − 1 ( i = 1 , 2 … , n ) b_i=a_i-a_{i-1} (i=1,2\dots,n) bi=aiai1(i=1,2,n)
 同时这个条件等价于
a i = b 1 + b 2 + ⋯ + b i a_i=b_1+b_2+\dots+b_i ai=b1+b2++bi
 此时我们称 数组 b i 为数组 a i 数组b_i为数组a_i 数组bi为数组ai差分 a i 为 b i a_i为b_i aibi前缀和

差分的应用

 假设我们有某种操作需要进行,这种操作给出一个连续区间 [ L , R ] [L,R] [L,R],接着我们需要对 a L 至 a R a_L至a_R aLaR的元素分别加上某个值c,如果不使用差分算法,那么这个操作的时间复杂度就是 O ( N ) O(N) O(N).如果使用差分算法,那么这些操作的时间夫再度将被简化到 O ( 1 ) O(1) O(1)

算法

 接下来我们探讨如何利用差分简化上述操作。
 如果要令 a L   a R a_L~a_R aL aR的元素都加上c,那么我们只需让 b L b_L bL加上c, b R + 1 b_{R+1} bR+1减去c即可,证明如下:
a L = b 1 + b 2 + ⋯ + b L a_L=b_1+b_2+\dots+b_L aL=b1+b2++bL
B L = b L + c B_L=b_L+c BL=bL+c
A L = b 1 + b 2 + ⋯ + B L A_L=b_1+b_2+\dots+B_L AL=b1+b2++BL
A L = a L + c A_L=a_L+c AL=aL+c
即当 b L b_L bL加上了c,对于任意的 i ( i > L ) i(i>L) i(i>L), a i a_i ai均加上了c,但由于我们指定了区间 [ L , R ] [L,R] [L,R],所以需要 b R + 1 b_{R+1} bR+1减去c,使得 a j ( j > R ) a_j(j>R) aj(j>R)的值恢复原状。

 现在我们若想更新 a L  至 a R a_L ~至a_R aL aR的值,只需要修改 b L 与 b R + 1 b_L与b_{R+1} bLbR+1的值,时间复杂度变成了 O ( 1 ) O(1) O(1)

代码

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

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

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

输入格式
第一行包含两个整数 n 和 m。

第二行包含 n 个整数,表示整数序列。

接下来 m 行,每行包含三个整数 l,r,c,表示一个操作。

输出格式
共一行,包含 n 个整数,表示最终序列。

数据范围
1≤n,m≤100000,
1≤l≤r≤n,1000≤c≤1000,1000≤整数序列中元素的值≤1000
输入样例:
6 3
1 2 2 1 2 1
1 3 1
3 5 1
1 6 1
输出样例:
3 4 5 3 4 2
//差分 时间复杂度 o(m)
#include<iostream>
using namespace std;
const int N = 1e5 + 10;
int a[N], b[N];
int main()
{
    int n, m;
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++)
    {
        scanf("%d", &a[i]);
        b[i] = a[i] - a[i - 1];      //构建差分数组
    }
    int l, r, c;
    while (m--)
    {
        scanf("%d%d%d", &l, &r, &c);
        b[l] += c;     //将序列中[l, r]之间的每个数都加上c
        b[r + 1] -= c;
    }
    for (int i = 1; i <= n; i++)
    {
        a[i] = b[i] + a[i - 1];    //前缀和运算
        printf("%d ", a[i]);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值