首页 > 编程语言 >算法学习笔记(5)——前缀和与差分

算法学习笔记(5)——前缀和与差分

时间:2022-12-09 22:11:06浏览次数:66  
标签:insert 前缀 int cin 差分 算法 数组

前缀和与差分

一维前缀和

前缀和可以用于快速计算一个序列的区间和,也有很多问题里不是直接用前缀和,但是借用了前缀和的思想。

用 \(s[i]\) 表示 \(a[0]+a[1]+\dots+a[i]\) 的和(所以称为前缀和),那么要计算区间 \([l, r]\) 的和,也就是计算 \(a[l]+a[l +1]+\dots+a[r]\),只需要计算 \(s[r] - s[l - 1]\) 就可以了,用 \(O(1)\) 的时间就可以计算出来。

题目链接:AcWing 795. 前缀和

#include <iostream>

using namespace std;

const int N = 100010;

int n, m;
int a[N], s[N]; // s[i]保存以i结尾的前缀和

int main()
{
    cin >> n >> m;
    
    for (int i = 1; i <= n; i ++ ) {
        cin >> a[i];
        s[i] = s[i - 1] + a[i];
    }
    
    while (m -- ) {
        int l, r;
        cin >> l >> r;
        cout << s[r] - s[l - 1] << endl;
    }
    
    return 0;
}

差分

差分是前缀和的逆运算,对于一个数组 \(a\),其差分数组 \(b\) 的每一项都是 \(a[i]\) 和前一项 \(a[i - 1]\) 的差,即 \(b[i] = a[i] - a[i - 1]\) 。和前缀和类似的,也是要留出索引是 \(0\) 的位置 \(b[0]=0\),方便计算。

对数组 \(b\) 求前缀和,可以发现就能得到数组 \(a\),所以它保留了数组 \(a\) 的全部信息。而将数组用其差分数组表示的一个优点就是能在 \(O(1)\) 时间里将数组中连续的一段加上一个数 \(c\)。

例如,要将 \(a\) 数组的 \([l, r]\) 全都加上 \(c\)。那么考虑到差分数组 \(b\) 求前缀和的时候就能恢复出 \(a\) 数组,可以发现 \(b[l]\) 前面的数都不用变。而只要将 \(b[l]\) 加上 \(c\),那么 \([l, +\infty]\) 就都加上了 \(c\)(因为从加到 \(b[l]\) 开始就加上了这个 \(c\),后面的所有加出来的 \(a[i]\) 就都比之前多 \(c\) 了)。然后将 \(b[r +1]\) 这个位置减去 \(c\),那么计算前缀和以恢复 \(a\) 的时候,到了 \(a[r + 1]\) 的位置就既没加 \(c\) 也没减 \(c\) 了,也就保证了 \([r + 1, +\infty]\) 是不变的。这样就实现了将 \([l, r]\) 这个区间里的所有数都加上 \(c\)。

题目链接:AcWing 797. 差分

#include <iostream>

using namespace std;

const int N = 100010;

int n, m;
int b[N];

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

int main()
{
    cin >> n >> m;
    
    int x;
    for (int i = 1; i <= n; i ++ ) cin >> x, insert(i, i, x);
    
    while (m -- ) {
        int l, r, c;
        cin >> 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 ++ ) cout << b[i] << ' ';
    
    return 0;
}

标签:insert,前缀,int,cin,差分,算法,数组
From: https://www.cnblogs.com/I-am-Sino/p/16970130.html

相关文章

  • 负环、差分约束和传递闭包
    差分约束https://oi-wiki.org/graph/diff-constraints/定义差分约束系统是一种特殊的\(n\)元一次不等式组,它包含\(n\)个变量\(x_1,...,x_n\)以及\(m\)个约束条......
  • 算法学习笔记(2)——归并排序
    归并排序归并排序的思想是基于分治法,其思路是:将待排序区间平分成左右两半,左右两侧分别递归地做归并排序。将这两个有序的区间合并(每次落一个较小的下来),就将这个区间排......
  • 算法学习笔记(1)——快速排序
    快速排序算法思想快排的思想是基于分治法,其思路是:确定分界点:给定要排序的数组q,先在数组中找一个数作为分界点值x,分界点可以取左边界值x=q[l],可以取右边界值x=q[r],......
  • crypto-gmsm国密算法库
    crypto-gmsm国密算法库一、开发背景crypto-gmsm国密算法库是国密商密算法(SM2,SM3,SM4)工具类封装,国产密码算法(国密算法)是指国家密码局认定的国产商用密码算法,目前主要使用......
  • 代码随想录算法训练营第三天 | 203.移除链表元素、707.设计链表、206.反转链表
    203. 移除链表元素tag:#链表leetcode地址:203. 移除链表元素代码:functionremoveElements(head:ListNode|null,val:number):ListNode|null{constnewH......
  • hutools密码算法库
    hutool密码算法库一、开发背景Hutool针对BouncyCastle做了简化包装,用于实现国密算法中的SM2、SM3、SM4。国密算法工具封装包括:非对称加密和签名:SM2摘要签名算法:SM3......
  • 【主色提取】模糊C均值(FCM )聚类算法和彩色图像快速模糊C均值( CIQFCM )聚类算法
    OverridetheentrypointofanimageIntroducedinGitLabandGitLabRunner9.4.Readmoreaboutthe extendedconfigurationoptions.Beforeexplainingtheav......
  • 零基预算法在全面预算管理中的应用
    随着经济不确定因素的不断扩大,大部分企业都或多或少的受到了影响。不难发现,如果仍然使用传统的预算编制方法,似乎并不像以往那样有效。不确定因素的影响使得数据在一定时期的......
  • 字符串的全排列算法讲解
    一、字符串的排列用C++写一个函数,如Foo(constchar*str),打印出str的全排列,如abc的全排列:abc,acb,bca,dac,cab,cba一、全排列的递归实现为方便起见,用123......
  • 冒泡排序算法详解C++程序
    (1)冒泡排序算法:(BubbleSort)首先肯定是一种简单的排序算法,它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到......