IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> C++数据结构与算法分析——前缀和与差分 -> 正文阅读

[数据结构与算法]C++数据结构与算法分析——前缀和与差分

前缀和

定义

假定有一数组 a [ 1 ] ~ a [ n ] a[1] \sim a[n] a[1]a[n],前缀和 s [ i ] s[i] s[i]就是前i项的和。
例如
s [ 1 ] = a [ 1 ] s[1] = a[1] s[1]=a[1]
s [ 2 ] = a [ 1 ] + a [ 2 ] s[2] = a[1] + a[2] s[2]=a[1]+a[2]
s [ n ] = a [ 1 ] + a [ 2 ] + . . . . . . + a [ n ] s[n] = a[1] + a[2] + ...... + a[n] s[n]=a[1]+a[2]+......+a[n]

应用

由此我们可以得到,若要求得数组 a [ l ] ~ a [ r ] a[l] \sim a[r] a[l]a[r]项的元素总和,只需要前r项的元素总和s[r]
减去前l-1项的元素总和s[l - 1]即可。

模板

// 前缀和模板
s[i] = a[1] + a[2] + a[3] + ...... + a[i];
a[l] + a[l + 1] + ... + a[r] = s[r] - s[l - 1];

例题

题目描述

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

接下来再输入 m 个询问,每个询问输入一对 l,r。

对于每个询问,输出原序列中从第 l 个数到第 r 个数的和。

输入格式

第一行包含两个整数nm

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

接下来m行,每行包含两个整数lr,表示一个询问的区间范围。

输出格式

共 m 行,每行输出一个询问的结果。

数据范围

1 ≤ l ≤ r ≤ n 1≤l≤r≤n 1lrn,
1 ≤ n , m ≤ 100000 1≤n,m≤100000 1n,m100000,
? 1000 ≤ 数 列 中 元 素 的 值 ≤ 1000 ?1000≤数列中元素的值≤1000 ?10001000

输入样例:

5 3
2 1 3 6 4
1 2
1 3
2 4

输出样例:

3
6
10

题解

对于每个询问的lr,都需要返回序列的区间 a [ l ] ~ a [ r ] a[l] \sim a[r] a[l]a[r]之和,根据模板很容易得出我们需要的代码

#include <iostream>
using namespace std;

const int N = 100010;
int n, m;
int s[N];


int main() {
    cin >> n >> m;
    for (int i = 1; i <= n; i++) cin >> s[i], s[i] += s[i - 1]; //求前缀和
    while (m--) {
        int l, r;
        cin >> l >> r;
        cout << s[r] - s[l - 1] << endl;
    }

    return 0;
}

注意事项

前缀和的数组从 a [ 1 ] a[1] a[1]开始是因为 s [ i ] = s [ i ? 1 ] + a [ i ] s[i] = s[i -1] + a[i] s[i]=s[i?1]+a[i]
假如从 a [ 0 ] a[0] a[0]开始的话 s [ 0 ] = s [ ? 1 ] + a [ 0 ] s[0] = s[-1] + a[0] s[0]=s[?1]+a[0]显然有问题。

差分

定义

假定有一数组 a [ 1 ] ~ a [ n ] a[1] \sim a[n] a[1]a[n],此时我们设一个数组 b [ 1 ] ~ b [ n ] b[1] \sim b[n] b[1]b[n],使得
a [ i ] = b [ 1 ] + b [ 2 ] + . . . + b [ i ] a[i] = b[1] + b[2] + ... + b[i] a[i]=b[1]+b[2]+...+b[i]
因此我们容易得出
b [ 1 ] = a [ 1 ] b[1] = a[1] b[1]=a[1]
b [ 2 ] = a [ 2 ] ? a [ 1 ] b[2] = a[2] - a[1] b[2]=a[2]?a[1]
b [ n ] = a [ n ] ? a [ n ? 1 ] b[n] = a[n] - a[n - 1] b[n]=a[n]?a[n?1]
由此我们也可以发现差分就是前缀和的逆运算

应用

差分可以解决一个区间[l,r]内同时加上或者减去同一个数的问题。
具体实现如下:
要实现a[l] ~ a[r]同时加上一个数c,我们首先从差分的定义入手
a[l - 1] = b[1] + b[2] + ... + b[l - 1]
a[l] = b[1] + b[2] + ... + b[l - 1] + b[l]
a[r] = b[1] + b[2] + ... + b[l - 1] + b[l] + b[l + 1] + ... + b[r]
a[r + 1] = b[1] + b[2] + ... + b[l - 1] + b[l] + b[l + 1] + ... + b[r] + b[r + 1]
从上面式子中我们可以发现a[l - 1]以后的元素都有b[l],而a[r + 1]以前的元素都没有b[r + 1]
因此要在a[l] ~ a[r]同时加上c,只要让b[l] + cb[r + 1] - c即可。

模板

给区间[l, r]中的每个数加上c:
B[l] += c, B[r + 1] -= c

例题

题目描述

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

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

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

输入格式

第一行包含两个整数 n 和 m。

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

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

输出格式

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

数据范围

1 ≤ n , m ≤ 100000 1≤n,m≤100000 1n,m100000,
1 ≤ l ≤ r ≤ n 1≤l≤r≤n 1lrn,
? 1000 ≤ c ≤ 1000 ?1000≤c≤1000 ?1000c1000,
? 1000 ≤ 整 数 序 列 中 元 素 的 值 ≤ 1000 ?1000≤整数序列中元素的值≤1000 ?10001000

输入样例:

6 3
1 2 2 1 2 1
1 3 1
3 5 1
1 6 1

输出样例:

3 4 5 3 4 2

题解

有了上面的分析,这题只要把b[1] ~ b[n]求出来,再套用模板即可AC。

#include<iostream>
using namespace std;

const int N = 1e5+10;
int a[N],b[N];

int main(){
    int n,m,tmp;
    scanf("%d%d",&n,&m);
    for(int i = 1; i <= n; i++){
        scanf("%d",&a[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;
    }
    
    int k = 0;
    for(int i = 1; i <= n; i++){
        k += b[i];
        printf("%d ",k);
    }
    
    return 0;
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-08-01 14:44:55  更:2021-08-01 14:45:18 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 18:25:44-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码