首页 > 其他分享 >前缀和和差分

前缀和和差分

时间:2025-01-12 16:45:50浏览次数:1  
标签:元素 前缀 int 单元格 差分 数组

一、一维前缀和:

  前缀和数组作用????   大量的区间求和,把原始数组a的区间操作转换为前缀和的两点操作

有一个数组{2,1,3,6,4},询问三次结果:
1. 数组第1到第2个元素的和是多少?
2. 数组第1到第3个元素的和是多少?
3. 数组第2到第4个元素的和是多少?

num:index:0 1 2 3 4 5 index
num:array: 2 1 3 6 4 a
sum-array 0 2 3 6 12 16 s

low high
1. 数组第1到第2个元素的和是多少?3 s[2]-s[0] = 3
2. 数组第1到第3个元素的和是多少?6 s[3]-s[0] = 6
3. 数组第2到第4个元素的和是多少?10 s[4]-s[1] = 10

s[high]-s[low-1]

 


[2,1,3,6,4] a数组 大量的区间求和

1. 数组第1到第2个元素的和是多少? a1+a2=3 暴力枚举的方法
2. 数组第1到第3个元素的和是多少? 6
3. 数组第2到第4个元素的和是多少? 10

num:index:0 1 2 3 4 5 index
num:array: 2 1 3 6 4 a
sum-array 0 2 3 6 12 16 s
原始数组 a [2,1,3,6,4] S4=a1+a2+a3+a4
前缀和数组S [2,3,6,12,16] S3= a3+S2=a1+a2+a3

前缀和数组作用???? 大量的区间求和,把原始数组a的区间操作转换为前缀和的两点操作

数组第i到第j个元素的和是多少 S[j]-S[i-1]

1. 数组第1到第2个元素的和是多少? S[2]-S[1-1] = 3-0=3
2. 数组第1到第3个元素的和是多少? S[3]-S[0]=6
3. 数组第2到第4个元素的和是多少? S[4]-S[1]=10

 

 1 // 一次性将在中间状态全部存储起来
 2 
 3 #include <stdio.h>
 4 #include <iostream>
 5 using namespace std;
 6 
 7 int main() {
 8     // 原始做法:
 9 //    int a[5] = {2, 1, 3, 6, 4};
10 //    for (int i = 0; i < 3; i++) {
11 //        int l, r;
12 //        cin >> l >> r;
13 //
14 //        int sum = 0;
15 //        for (int j = l - 1; j < r; j++) {
16 //            sum += a[j];
17 //        }
18 //
19 //        cout << "sum: " << sum << endl;
20 //    }
21 
22     // 前缀和做法
23     int a[5] = {2, 1, 3, 6, 4};
24     int s[6];   // 定义a数组的前缀和数组
25     s[0] = 0;
26 
27     for (int i = 1; i < 6; i++) {
28         s[i] = s[i - 1] + a[i - 1];
29     }
30 
31     for (int i = 0; i < 3; i++) {
32         int l, r;
33         cin >> l >> r;
34         cout << s[r] - s[l - 1]<<endl;
35     }
36     
37     return 0;
38 }

 二、一维差分:

1. 现在有一个数列a[0 0 0 0 0 0],现在想对第3个到第5个元素统一进行加2操作
a[0 0 2 2 2 0]
差分数组d就是相邻两个元素的差排列出来的数列
原始数列a[0 0 0 0 0 0]的差分数列是 d[0 0 0 0 0 0]
一维差分的作用:大量的区间统一更新操作改为两点之间的操作

第3个到第5个元素统一进行加2操作就可以用差分数组的两点操作来完成:
(1) 把差分数组的第3个元素加2,然后把第5+1个位置的元素减2:d[0 0 2 0 0 -2]
(2) 求出这个差分数组的前缀和数组就是我们要的答案:[0 0 2 2 2 0]

 

 1 #include <iostream>
 2 using namespace std;
 3 
 4 int main() {
 5     int n, m, num[10], diff[10];
 6     cin >> n >> m; // 输入的n表示数组元素个数,m表示一共想进行多少次差分数组的统一操作
 7     for (int i = 1; i <= n; i++) {
 8         cin >> num[i];    // 初始化数组里的数据
 9     }
10     for (int i = 1; i <= n; i++) {
11         diff[i] = num[i] - num[i - 1];  // 差分数组初始化
12     }
13     for (int i = 0; i < m; i++) {
14         int a, b, c;
15         cin >> a >> b >> c;  //  a,b,c分别表示区间起止和需要修改的值
16         diff[a] += c;        // 差分数组的第a号位置 +c     
17         diff[b + 1] -= c;    // 差分数组的第b+1号位置 -c
18     }
19     for(int i=1;i<=n;i++){        // 把差分数组还原到原数组中去
20         num[i]=num[i-1]+diff[i];
21     }
22     for(int i=1;i<=n;i++){        //  输出操作后的数组里的值
23         cout<<num[i]<<" ";
24     }
25 
26     return 0;
27 }

三、二维前缀和:

1. 如果起始单元格从第一个单元格开始
S[i][j] = S[i][j-1] + S[i-1][j] - S[i-1][j-1] + a[i][j];
2. 如果起始单元格不是从第一个单元格开始,起止单元格分别是:(x1,y1),(x2,y2)
S[x2][y2] - S[x1-1][y2] - S[x2][y1-1] + S[x1-1][y1-1]

4 5 1
1 2 2 1 3
3 2 2 1 1
1 1 1 1 1
2 1 3 2 1
2 2 3 4
3. 最终可以把二维原始数组中的区域求和操作转换为这个二维数组前缀和数组的某四个点位之间的操作,这个点位操作
的公式是:
S[x2][y2] - S[x1 - 1][y2] - S[x2][y1 - 1] + S[x1 - 1][y1 - 1]

 1 #include <iostream>
 2 using namespace std;
 3 
 4 const int N = 1010;
 5 int n, m, q;
 6 int a[N][N], S[N][N];
 7 
 8 /*
 9     二维前缀和公式:
10     1. 如果起始单元格从第一个单元格开始
11         S[i][j] = S[i][j-1] + S[i-1][j] - S[i-1][j-1] + a[i][j];
12     2. 如果起始单元格不是从第一个单元格开始,起止单元格分别是:(x1,y1),(x2,y2)
13         S[x2][y2] - S[x1-1][y2] - S[x2][y1-1] + S[x1-1][y1-1]
14 
15     示例数据:
16     4 5 1
17     1 2 2 1 3
18     3 2 2 1 1
19     1 1 1 1 1
20     2 1 3 2 1
21     2 2 3 4
22 
23 */
24 int main() {
25     scanf("%d%d%d", &n, &m, &q);
26     for (int i = 1; i <= n; ++i)
27         for (int j = 1; j <= m; ++j)
28             scanf("%d", &a[i][j]);
29 
30     for (int i = 1; i <= n; ++i) {
31         for (int j = 1; j <= m; ++j)
32             S[i][j] = S[i][j - 1] + S[i - 1][j] - S[i - 1][j - 1] + a[i][j]; // 初始化每个单元格的前缀和
33     }
34     
35     // 输出前缀和
36 //    for(int i=1;i<=n;i++){
37 //        for(int j=1;j<=m;j++){
38 //            printf("%d ",S[i][j]);
39 //        }
40 //        printf("\n");
41 //    }
42 
43     while (q--) {
44         int x1, y1, x2, y2;
45         scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
46         printf("%d\n", S[x2][y2] - S[x1 - 1][y2] - S[x2][y1 - 1] + S[x1 - 1][y1 - 1]);  // 具体计算某个单元格到某个单元格之间的前缀和
47     }
48 
49     return 0;
50 }

 

标签:元素,前缀,int,单元格,差分,数组
From: https://www.cnblogs.com/SIPnnnnn/p/18666980

相关文章

  • Atcoder ABC387F Count Arrays 题解 [ 绿 ] [ 基环树 ] [ 树形 dp ] [ 前缀和优化 ]
    CountArrays:一眼秒的计数题。思路显然,把小于等于的条件化为大的向小的连单向边,每个数的入度都是\(1\),就会形成一个基环树森林。那么考虑这个环上能填什么数。因为所有数都小于等于他后面的数,所以所有数都只能相等。这就启发我们在基环树上缩点之后再进行计数。那么当缩完点......
  • D - Coming of Age Celebration (前缀+差分)
    题目链接:https://atcoder.jp/contests/abc388/tasks/abc388_d题意:一共有n个外星人,每当有一个外星人成年后,成年的外星人就要给他一块钱(如果没钱就不给),返回操作后数组思路:模拟一下,可以把数组前面已经成年的外星人对下一个刚好要成年的外星人的钱数贡献记作前缀信息s,随着数......
  • Java-前缀树
        前缀树,也叫Trie树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:最大限度地减少无谓的字符串比较。        Trie树的核心思想是空间......
  • 前缀和,差分与离散化
    前缀和:前缀和顾名思义一般是指数组中前n项的和,通常用另一个数组来存储,如定义一个前缀和数组prefix[n]表示的是a1+a2+--an,这与等差数列中的Sn有着相像之处,但如何用代码实现的呢?只需要定义一个前缀和数组--prefix[n]for(inti=1;i<=n;i++){prefix[i]=prefix[i-1]+a[i];}......
  • 随笔:我为什么没有把《P5369 [PKUSC2018] 最大前缀和》做出来
    这是一篇随笔(绝对不是某CC风格的随笔)特别提醒:某W同学,再被【数据删除】要求写【数据删除】时你可以看一看这个大纲。我在干什么我在考【数据删除】时,开完题目后,我断定我就要解决这一道题。看见\(20\)这个小范围以后我就想起上一把【数据删除】的T【数据删除】。我就想DP......
  • 704 二维差分
    //704二维差分.cpp:此文件包含"main"函数。程序执行将在此处开始并结束。///*http://oj.daimayuan.top/course/22/problem/895给一个n×m的矩阵a1,1,a1,2,…,a1,m,…,an,m和q个修改操作。一开始所有位置都是0,每次修改给出五个数x1,y1,x2,y2,d,令所有ai,j(x1≤......
  • 高斯金字塔,高斯模糊,高斯差分
    高斯金字塔、高斯模糊和高斯差分是图像处理中非常重要的技术,常用于图像缩放、降噪、特征提取等领域。1.高斯模糊(GaussianBlur)高斯模糊是一种降噪技术,基于高斯函数的图像处理技术,用于平滑图像,减少噪声或细节。它在图像处理和计算机视觉中非常常用,尤其是在预处理步骤中,通过对图......
  • 208. 实现 Trie (前缀树)
    [题目链接](208.实现Trie(前缀树)-力扣(LeetCode))解题思路:前缀树,每个节点的内容:pre:经过该节点的数目;end:以该节点结尾的数目;nexts:下一条路径。前缀树有一个根节点,每次查找、插入、删除都要从这个节点开始。插入时,遍历该字符串,先从根节点开始,查看nexts是否有该字符,有就复......
  • 时序差分(Temporal Difference, TD)学习的详细介绍-ChatGPT4o作答
    时序差分(TemporalDifference,TD)学习的详细介绍时序差分(TemporalDifference,TD)是一种强化学习中重要的价值函数估计方法,结合了动态规划(DynamicProgramming)和蒙特卡洛方法(MonteCarlo)的优点。它通过从经验中直接学习预测值,而不需要完整的回报序列,能够高效地处理马尔科夫......
  • 并行前缀(Parallel Prefix)加法器
    并行前缀(ParallelPrefix)加法器并行前缀加法器的基本介绍二进制加法器是目前数字计算单元中的重要模块,基础的加法器架构包括行波进位加法器(RippleCarryAdder),超前进位加法器(CarryLook-AheadAdder),进位选择加法器(CarrySelectAdder)等。加法器的进位传播是其组合延迟的主要来源......