首页 > 其他分享 >前缀和

前缀和

时间:2023-04-22 22:46:15浏览次数:40  
标签:前缀 int sum y1 x2 y2

算法简介

前缀和用于快速得到数组某个连续区间内所有元素的元素和。

时间复杂度

构建前缀和数组:\(O(n)\)
求取某区间总和:\(O(1)\)

实现原理

按照如下规则构建前缀和数组:

例如:有数组 \(a\),前缀和数组为 \(s\)。
\(s[0] = 0\)
\(s[1] = a[1]\)
\(s[2] = a[2] + a[1]\)
...
\(s[n] = a[n] + a[n-1] + a[n-2] + \cdots + a[1]\)

那么求取某一区间 [l,r] 即可用 s[r] - s[l-1] 取得

如求 \(a[3] + a[4] + a[5]\) 的和,则有:
\(s[5] = a[5] + a[4] + a[3] + a[2] + a[1]\)
\(s[2] = a[2] + a[1]\)
则有 \(a[3] + a[4] + a[5] = s[5] - s[2] = a[5] + a[4] + a[3] + a[2] + a[1] - a[2] - a[1]\)

算法实例

1. 题目描述

https://www.acwing.com/problem/content/description/797/

2. AC代码

#include <bits/stdc++.h>

const int N = 100010;

int n,m;
int sum[N],a[N];

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

算法拓展

二维前缀和

二维前缀和就是将一维前缀和扩展到二维,快速求取某个子矩阵元素和的算法。

其中前缀和数组 sum[i,j] 表示 [1,1] 到 [i,j] 这个子矩阵的元素和。

sum[i,j] 即为红色框矩阵的和:

求解二维前缀和需要明确两个问题:

  1. 如何构造 sum 数组:
    \(sum[i][j] = sum[i-1][j] + sum[i][j-1] - sum[i-1][j-1] + a[i][j]\)


整个外围蓝色矩形面积s[i][j] = 绿色面积s[i-1][j] + 紫色面积s[i][j-1] - 重复加的红色的面积s[i-1][j-1]+小方块的面积a[i][j];

  1. 如何求解以 [x1,y1] 为左上角坐标,[x2,y2] 为右下角坐标的子矩阵的矩阵和。
    \(sum[x2][y2] - sum[x1-1][y2] - sum[x2][y1-1] + sum[x1-1][y1-1]\)


绿色矩形的面积 = 整个外围面积s[x2, y2] - 黄色面积s[x2, y1 - 1] - 紫色面积s[x1 - 1, y2] + 重复减去的红色面积 s[x1 - 1, y1 - 1]

题目实例

https://www.acwing.com/problem/content/description/798/

AC代码

#include <iostream>

using namespace std;

typedef long long LL;

const int N = 1010;

LL a[N][N],s[N][N];

int main()
{
    int n,m,q;
    cin >> n >> m >> q;
    
    for (int i = 1 ; i <= n ; i ++ )
        for (int j = 1 ; j <= m ; j ++ )
            cin >> a[i][j];
            
    for (int i = 1 ; i <= n ; i ++ )
        for (int j = 1 ; j <= m ; j ++ )
            s[i][j] = s[i][j-1] + s[i-1][j] - s[i-1][j-1] + a[i][j];
    
    while(q--)
    {
        int x1,y1,x2,y2;
        cin >> x1 >> y1 >> x2 >> y2;
        cout << s[x2][y2] - s[x1-1][y2] - s[x2][y1-1] + s[x1-1][y1-1] << endl;
    }
    return 0;
}

参考

[1] https://www.acwing.com/solution/content/3797/
[2] https://www.acwing.com/solution/content/27301/

标签:前缀,int,sum,y1,x2,y2
From: https://www.cnblogs.com/NachoNeko/p/17321235.html

相关文章

  • 一维与二维前缀和(蓝桥杯复习+例题讲解+模板c++)
    文章目录前缀和二维前缀和总结3956.截断数组99.激光炸弹前缀和前缀和是一种常见的算法,用于快速计算数组中某一段区间的和。前缀和的思想就是预处理出数组中前缀和,然后用后缀和减去前缀和,即可快速计算区间和。以一维数组为例,设表示数组中第个元素的值,表示数组中前个元素的......
  • 【ACM算法竞赛日常训练】DAY16【奇♂妙拆分】【区区区间间间】【小AA的数列】数学 |
    DAY16共3题:奇♂妙拆分(简单数学)区区区间间间(单调栈)小AA的数列(位运算dp)......
  • 【前缀和】LeetCode 523. 连续的子数组和
    题目链接523.连续的子数组和思路参考宫水三叶大佬题解一开始以为和Leetcode53MaximumSubarray思路差不多,都是求子数组的值。但是后来发现在53题中并没有求出每个子数组的和,只是在贪心的情况下求出了可能的最大和代码classSolution{publicbooleancheckSubarra......
  • LeetCode 周赛 340,质数 / 前缀和 / 极大化最小值 / 最短路 / 平衡二叉树
    本文已收录到AndroidFamily,技术和职场问题,请关注公众号[彭旭锐]提问。大家好,我是小彭。上周跟大家讲到小彭文章风格的问题,和一些朋友聊过以后,至少在算法题解方面确定了小彭的风格。虽然竞赛算法题的文章受众非常小,但却有很多像我一样的初学者,他们有兴趣参加但容易被题目难......
  • 【前缀和】LeetCode 1031. 两个非重叠子数组的最大和
    题目链接1031.两个非重叠子数组的最大和思路代码classSolution{publicintmaxSumTwoNoOverlap(int[]nums,intfirstLen,intsecondLen){//求一个前缀和for(inti=1;i<nums.length;++i){nums[i]+=nums[i-1];}......
  • 前缀和
    链接:https://ac.nowcoder.com/acm/contest/55407/E来源:牛客网给定n个整数a1,a2,···,an ,求它们两两相乘再相加的和,即S=a1 ·a2 +a1 ·a3 +···+a1 ·an +a2 ·a3 +···+an-2 ·an-1 +an-2 ·an +an-1 ·an.输入描述:#inc......
  • 前缀和与差分
    1.K倍区间来源:第八届蓝桥杯省赛C++B组,第八届蓝桥杯省赛JAVAB组原题链接题目描述给定一个长度为\(N\)的数列,\(A_1,A_2,…A_N\),如果其中一段连续的子序列\(A_i,A_{i+1},…A_j\)之和是\(K\)的倍数,我们就称这个区间\([i,j]\)是\(K\)倍区间。你能求出数列中总共有多......
  • 前缀和-leetcode303
    LeetCode上的题目"303.区域和检索-数组不可变",是一个相对简单的问题。问题描述:给定一个整数数组nums,求出该数组从索引i到j(i≤j)范围内元素的总和,包含i,j两点。实现NumArray类:NumArray(int[]nums)用整数数组nums初始化对象intsumRange(inti,intj)返回......
  • js用前缀名查找class或id节点,js模糊查询某个dom节点
    js在操作dom的场景中,有时候会有类似的场景需求。js用前缀名查找class节点//参数dom为htmldom节点//参数key为需模糊查询的名称字段functionqueryClassNode(dom,key){letcollectArray=[];for(vari=0;i<dom.childNodes.length;i++){ //核心点......
  • 用前缀树实现中文敏感词过滤器
    前言本文代码实现一个中文的敏感词过滤器,预先将准备好的敏感词写入前缀树数据结构中实现快速检索,并且节省内存。一般用于检查注册用户名称、言论是否包含不文明的词汇。可以判断内容是否包含敏感词;找出内容中的敏感词;将内容中的敏感词替换成设置的字符。运行环境代码使用了JDK......