当前位置: 首页 > news >正文

前缀和相关题目记录(未完待续...)

1 前缀和

一维前缀和是指对于一个数组 a a a,我们定义一个新的数组 s s s,其中每个元素 s [ i ] s[i] s[i] 表示从数组开头到第 i i i 个元素的累加和:

s [ i ] = a [ 1 ] + a [ 2 ] + ⋯ + a [ i ] = ∑ j = 1 i a [ j ] s[i] = a[1] + a[2] + \cdots + a[i] = \sum_{j=1}^{i} a[j] s[i]=a[1]+a[2]++a[i]=j=1ia[j]

通过预处理前缀和数组 s s s,我们可以快速计算任意区间 [ l , r ] [l, r] [l,r] 的和:

sum ( l , r ) = s [ r ] − s [ l − 1 ] \text{sum}(l, r) = s[r] - s[l - 1] sum(l,r)=s[r]s[l1]

如果 l = 1 l = 1 l=1,则 sum ( l , r ) = s [ r ] \text{sum}(l, r) = s[r] sum(l,r)=s[r]

二维前缀和是前缀和思想的扩展,适用于矩阵。对于一个 n × m n \times m n×m 的矩阵 a a a,我们定义一个二维前缀和矩阵 s s s,其中 s [ i ] [ j ] s[i][j] s[i][j] 表示从矩阵左上角 ( 1 , 1 ) (1, 1) (1,1) 到右下角 ( i , j ) (i, j) (i,j) 的所有元素的和:
s [ i ] [ j ] = ∑ x = 1 i ∑ y = 1 j a [ x ] [ y ] s[i][j] = \sum_{x=1}^{i} \sum_{y=1}^{j} a[x][y] s[i][j]=x=1iy=1ja[x][y]

通过二维前缀和矩阵 s s s,我们可以快速计算任意子矩阵 ( x 1 , y 1 ) (x_1, y_1) (x1,y1) ( x 2 , y 2 ) (x_2, y_2) (x2,y2) 的和:
s ( x 1 , y 1 , x 2 , y 2 ) = s [ x 2 ] [ y 2 ] − s [ x 1 − 1 ] [ y 2 ] − s [ x 2 ] [ y 1 − 1 ] + s [ x 1 − 1 ] [ y 1 − 1 ] {s}(x_1, y_1, x_2, y_2) = s[x_2][y_2] - s[x_1-1][y_2] - s[x_2][y_1-1] + s[x_1-1][y_1-1] s(x1,y1,x2,y2)=s[x2][y2]s[x11][y2]s[x2][y11]+s[x11][y11]


2 一维板子

原题链接:DP34 【模板】前缀和

给定一个长度为 n n n 的数组 a 1 , a 2 , . . . , a n a_1, a_2, ..., a_n a1,a2,...,an。接下来有 q q q 次查询,每次查询有两个参数 l , r l, r l,r。对于每个询问,请输出 a l + a l + 1 + . . . + a r a_l + a_{l+1} + ... + a_r al+al+1+...+ar

输入描述:

第一行包含两个整数 n n n q q q,第二行包含 n n n 个整数,表示 a 1 , a 2 , . . . , a n a_1, a_2, ..., a_n a1,a2,...,an。接下来 q q q 行,每行包含两个整数 l l l r r r

  • 1 ≤ n , q ≤ 1 0 5 1 \leq n, q \leq 10^5 1n,q105
  • − 1 0 9 ≤ a [ i ] ≤ 1 0 9 -10^9 \leq a[i] \leq 10^9 109a[i]109
  • 1 ≤ l ≤ r ≤ n 1 \leq l \leq r \leq n 1lrn

输出描述:
输出 q q q 行,每行代表一次查询的结果。

示例:
input:

3 2
1 2 4
1 2
2 3

output:

3
6
#include <iostream>
#include <vector>
using namespace std;#define endl '\n'
#define LL long longvector<LL> a(101010, 0);
vector<LL> s(101010, 0);int main()
{int n, q;cin >> n >> q;for (int i = 1; i <= n; i++) {cin >> a[i];s[i] = s[i - 1] + a[i];}while (q--) {int l, r;cin >> l >> r;cout << s[r] - s[l - 1] << endl;}return 0;
}

时间复杂度: 预处理前缀和数组的时间复杂度为 O ( n ) O(n) O(n),每次查询的时间复杂度为 O ( 1 ) O(1) O(1)


3 二维板子

原题链接:DP35 【模板】二维前缀和

给你一个 n n n m m m 列的矩阵 A A A,下标从1开始。接下来有 q q q 次查询,每次查询输入4个参数 x 1 x_1 x1, y 1 y_1 y1, x 2 x_2 x2, y 2 y_2 y2。请输出以 ( x 1 , y 1 ) (x_1, y_1) (x1,y1) 为左上角, ( x 2 , y 2 ) (x_2, y_2) (x2,y2) 为右下角的子矩阵的和。

输入描述:
第一行包含三个整数 n n n, m m m, q q q

接下来 n n n 行,每行 m m m 个整数,代表矩阵的元素。

接下来 q q q 行,每行4个整数 x 1 x_1 x1, y 1 y_1 y1, x 2 x_2 x2, y 2 y_2 y2,分别代表这次查询的参数。

  • 1 ≤ n , m ≤ 1000 1 \leq n, m \leq 1000 1n,m1000
  • 1 ≤ q ≤ 1 0 5 1 \leq q \leq 10^5 1q105
  • − 1 0 9 ≤ a [ i ] [ j ] ≤ 1 0 9 -10^9 \leq a[i][j] \leq 10^9 109a[i][j]109
  • 1 ≤ x 1 ≤ x 2 ≤ n 1 \leq x_1 \leq x_2 \leq n 1x1x2n
  • 1 ≤ y 1 ≤ y 2 ≤ m 1 \leq y_1 \leq y_2 \leq m 1y1y2m

输出描述:
输出 q q q 行,每行表示查询结果。

示例

输入:

3 3 2
1 2 3
4 5 6
7 8 9
1 1 2 2
2 2 3 3

输出:

12
26
#include <iostream>using namespace std;long long a[1010][1010];
long long s[1010][1010];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 - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + a[i][j];}}int x1, x2, y1, y2;while (q--) {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:724.寻找数组中心下标 - e

724.寻找数组的中心下标 - easy

#include <iostream>
#include <vector>
using namespace std;/*
https://leetcode.cn/problems/find-pivot-index/description/
正常思路应该是:
2 * left_sum = sumclass Solution {
public:int pivotIndex(vector<int>& nums) {int sum = reduce(nums.begin(), nums.end());int left = 0;for (int i = 0; i < nums.size(); i++) {if (2 * left  == sum - nums[i]) {return i;}left += nums[i];}return -1;}
};*/class Solution {
public:int pivotIndex(vector<int>& nums){int n = nums.size();if (n == 0)return -1;// 前缀和数组,dp1[i] 表示 nums[0] 到 nums[i-1] 的和vector<int> dp1(n + 1, 0); // 后缀和数组,dp2[i] 表示 nums[i+1] 到 nums[n-1] 的和vector<int> dp2(n + 1, 0); for (int i = 1; i <= n; ++i) {dp1[i] = dp1[i - 1] + nums[i - 1];}for (int i = n - 1; i >= 0; --i) {dp2[i] = dp2[i + 1] + nums[i];}for (int i = 0; i < n; ++i) {if (dp1[i] == dp2[i + 1]) {return i;}}return -1;}
};int main()
{vector<int> nums = { 1, 7, 3, 6, 5, 6 };Solution sol;int ans = sol.pivotIndex(nums);cout << ans << endl;
}

习题2:303.区域和检索数组不可变 - e

303. 区域和检索 - 数组不可变 - easy

// https://leetcode.cn/problems/range-sum-query-immutable/
#include <iostream>
#include <vector>
using namespace std;
class NumArray {vector<int> s;
public:NumArray(vector<int>& nums){s.resize(nums.size() + 1);for (int i = 0; i < nums.size(); i++) {s[i + 1] = s[i] + nums[i];}}int sumRange(int left, int right){return s[right + 1] - s[left];}
};

习题3:238.除自身以外数组的乘积 - m

238. 除自身以外数组的乘积 - m

/* https://leetcode.cn/problems/product-of-array-except-self/description/ */#include <iostream>
#include <vector>
using namespace std;
class Solution {
public:vector<int> productExceptSelf(vector<int>& nums){int n = nums.size();vector<int> ans(n, 1);for (int i = 1; i < n; i++)ans[i] = ans[i - 1] * nums[i - 1];int suffix = 1;for (int i = n - 1; i >= 0; i--) {ans[i] = ans[i] * suffix;suffix *= nums[i];}return ans;}
};int main()
{vector<int> nums1 = { 1, 2, 3, 4 };Solution sol;vector<int> result1 = sol.productExceptSelf(nums1);for (int num : result1) {cout << num << " ";}cout << endl;
}/*class Solution {
public:vector<int> productExceptSelf(vector<int>& nums) {int n = nums.size();vector<int> pre(n, 1);for (int i = 1; i < n; i++) {pre[i] = pre[i - 1] * nums[i - 1];}vector<int> suf(n, 1);for (int i = n - 2; i >= 0; i--) {suf[i] = suf[i + 1] * nums[i + 1];}vector<int> ans(n);for (int i = 0; i < n; i++) {ans[i] = pre[i] * suf[i];}return ans;}
};*/

习题4:

在这里插入图片描述

http://www.lryc.cn/news/542202.html

相关文章:

  • Https解决了Http的哪些问题
  • OpenCV给图像添加噪声
  • 湖北中医药大学谱度众合(武汉)生命科技有限公司研究生工作站揭牌
  • 欢乐力扣:快乐数
  • 【聊天室后端服务器开发】功能设计-框架与微服务
  • 国标28181协议在智联视频超融合平台中的接入方法
  • 让网页“浪“起来:打造会呼吸的波浪背景
  • linux-多进程基础(1) 程序、进程、多道程序、并发与并行、进程相关命令,fork
  • 美颜相机1.0
  • Docker内存芭蕾:优雅调整容器内存的极限艺术
  • gitlab初次登录为什么登不上去
  • 单链表相关操作(基于C语言)
  • SPRING10_SPRING的生命周期流程图
  • 从零到一学习c++(基础篇--筑基期十一-类)
  • Java String 类
  • P8665 [蓝桥杯 2018 省 A] 航班时间
  • Vue3项目与pnpm使用教程
  • C++初阶——简单实现list
  • C/C++后端开发面经
  • linux 编辑器
  • 【事件驱动框架OSAL】二.消息的管理机制
  • 《论多源数据集成及应用》审题技巧 - 系统架构设计师
  • 【企业微信开发工具,获取位置】
  • HTML之JavaScript DOM编程获取元素的方式
  • 如何安装vm和centos
  • docker 安装redis 7.4.2并挂载配置文件以及设置密码
  • 计算机毕业设计SpringBoot+Vue.js在线教育系统(源码+文档+PPT+讲解)
  • Linux-C-函数栈-SP寄存器
  • vi的基本使用
  • clickhouse--表引擎的使用