【算法挨揍日记】day13—— DP34 【模板】前缀和、DP35 【模板】二维前缀和

DP34 【模板】前缀和

【模板】前缀和_牛客题霸_牛客网

题目描述:

给定一个长度为n的数组. 接下来有q次查询, 每次查询有两个参数l, r. 对于每个询问, 请输出

输入描述:

第一行包含两个整数n和q.第二行包含n个整数, 表示.接下来q行,每行包含两个整数 l和r.

输出描述:

输出q行,每行代表一次查询的结果.

示例1

输入

3 2

1 2 4

1 2

2 3

输出

3

6

解题思路:

我们可以可以通过暴力的解法去解决这个问题,但是这样时间复杂度会比较高,达到O(n*q)

我们可以对暴力解法进行优化:

我们以【1,4,7,2,5,8,3,6,9】这个数组来讲解前缀和(快速求出数组中某个连续区间的元素和)这个算法

index为数组下标,至于为什么下标从一开始后面会讲!!!

我们提前弄一个前缀和数组dp,这个数组的元素dp【i】代表【1,i】区间内所有元素之和

我们在求dp的时候肯定不可以用暴力解法,不然的话时间复杂度又上去了,

dp【i】代表 【1,i】区间内所有元素之和,那dp【i-1】代表 【1,i-1】区间内所有元素之和

  • dp【i】就可以等于dp【i-1】+arr【i】

那我们再来看看题目,题目要求我们输出从l到r区间内所有元素之和

那我们可以直接输出dp【r】-dp【l-1】

  • 这里我们把下标设为1开始,是因为我们的dp在算的时候会用到i-1的位置,如果i从0开始就会出现越界的情况

解题代码:

cpp 复制代码
#include <iostream>
#include<vector>
using namespace std;
int main() {
    int n,q;
    cin>>n>>q;
    vector<int> arr(n+1);
    for(int i=1;i<=n;i++) cin>>arr[i];
    vector<long long> dp(n+1);
    for(int i=1;i<=n;i++) dp[i]=dp[i-1]+arr[i];
    while(q--)
    {
        int l,r;
        cin>>l>>r;
        cout<<dp[r]-dp[l-1]<<endl;
    }
    return 0;
}
// 64 位输出请用 printf("%lld")

DP35 【模板】二维前缀和

题目描述:

请输出以 (x1, y1) 为左上角 , (x2,y2) 为右下角的子矩阵的和,

输入描述:

第一行包含三个整数n,m,q.

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

接下来q行,每行4个整数x1, y1, x2, y2,分别代表这次查询的参数

解题思路:

首先如果我们使用暴力解法时间复杂度,直接就是O(n*m*q),我们可以对其使用前缀和算法优化

我们可以创建一个(n+1)*(m+1)的的数组arr和(n+1)*(m+1)的的前缀和数组dp

  • 这里数组坐标加一也是为了防止越界的情况

dp【i】【j】代表从(1,1)~(i,j)这个区间内所有元素之和

我们如何快速求出dp【i】【j】的值呢?以下面这个数组为例,假设我们要求的是dp【3】【3】

我们先来观察一个通用图:我们要求多少A+B+C+D之和

A+B+C+D=(A+B)+(A+C)+D-A,括号内的是一个整体

我们可以结合下标的关系推导进一步的关系

A+B+C+D=(A+B)+(A+C)+D-A

=dp【i-1】【j】+dp【i】【j-1】+arr【i】【j】-dp【i-1】【j-1】

这样我们就求出来了dp的每一个数了,回到题目上,题目要求我们输出(x1,y1)~(x2,y2)这个区间内的所有元素之和,假设让我们输出是是这个区间

  • D=(A+B+C+D)-(A+B)-(A+C)+A

D=(A+B+C+D)-(A+B)-(A+C)+A

= dp【x2】【y2】-dp【x1-1】【y2】-dp【x2】【y1-1】+dp【x1-1】【y1-1】

为了防止越界,我们开辟数组也要多开一行一列

解题代码:

cpp 复制代码
#include <iostream>
#include<vector>
using namespace std;
int main() {
    int n,m,q;
    cin>>n>>m>>q;
    int arr[n+1][m+1];
    long long dp[n+1][m+1];
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            cin>>arr[i][j];
            dp[i][j]=dp[i-1][j]+dp[i][j-1]+arr[i][j]-dp[i-1][j-1];
        }
    }
    while(q--)
    {
        int x1,x2,y1,y2;
        cin>>x1>>y1>>x2>>y2;
        cout<<dp[x2][y2]-dp[x1-1][y2]-dp[x2][y1-1]+dp[x1-1][y1-1]<<endl;
    }
    return 0;
}
// 64 位输出请用 printf("%lld")
相关推荐
焦耳加热3 小时前
阿德莱德大学Nat. Commun.:盐模板策略实现废弃塑料到单原子催化剂的高值转化,推动环境与能源催化应用
人工智能·算法·机器学习·能源·材料工程
wan5555cn3 小时前
多张图片生成视频模型技术深度解析
人工智能·笔记·深度学习·算法·音视频
u6064 小时前
常用排序算法核心知识点梳理
算法·排序
蒋星熠6 小时前
Flutter跨平台工程实践与原理透视:从渲染引擎到高质产物
开发语言·python·算法·flutter·设计模式·性能优化·硬件工程
小欣加油6 小时前
leetcode 面试题01.02判定是否互为字符重排
数据结构·c++·算法·leetcode·职场和发展
3Cloudream6 小时前
LeetCode 003. 无重复字符的最长子串 - 滑动窗口与哈希表详解
算法·leetcode·字符串·双指针·滑动窗口·哈希表·中等
王璐WL6 小时前
【c++】c++第一课:命名空间
数据结构·c++·算法
空白到白7 小时前
机器学习-聚类
人工智能·算法·机器学习·聚类
索迪迈科技7 小时前
java后端工程师进修ing(研一版 || day40)
java·开发语言·学习·算法
zzzsde7 小时前
【数据结构】队列
数据结构·算法