算法学习笔记(2)-前缀和

##前缀和

指的是某序列的前n项和,在数学上我们可以理解称为数列的前n项和。前缀和是一种预处理,用于降低查询的时间复杂度。

##一维前缀和

有一个一维数组x和该数组的前缀和数组y,则x和y具有以下关系:

#python代码示例

复制代码
#关系:y0 = x0, y1 = x0 + x1, y2 = x0 + x1 + x2……
#python示例
for i,x in enumerate(x):
    if i == 0 :
        y[i] = x[i]
    else:
        y[i] = y[i-1] + x[i]
python 复制代码
arr = [1,2,3,4,5]
sum = [0] * (5 + 6)
sum[0] = 0 
for i,x in enumerate(arr):
    sum[i] = arr[i - 1] + sum[i - 1]
for i,x in enumerate(sum):
    print("{}-{}".format(i,x))

#c++代码示例

#关系:y0 = x0, y1 = x0 + x1, y2 = x0 + x1 + x2......

#c++示例

for (int i = 0 ; i < n ; i++)

{

if (i == 0)

{

y[i] = x[i] ;

}

else

{

y[i] = y[i-1] + x[i] ;

}

}

cpp 复制代码
#include<bits/stdc++.h>
using namespace std ;

int main()
{
    int arr[5] = {1,2,3,4,5} ;
    int sum[6] ;
    sum[0] = 0 ;
    for (int i = 1 ; i < 6 ; i++)
    {
        sum[i] = arr[i - 1] + sum[i - 1] ;
    }
    
    for (auto i : sum)
    {
        cout << i <<' ';
    }
    return 0 ;
}

【模板】前缀和_牛客题霸_牛客网 (nowcoder.com)

cpp 复制代码
//c++代码示例
#include <iostream>
using namespace std;
int a[101010] ;
long long sum[101010] ;
int main() {
    int n,q;
    cin >> n >> q ;
    for (int i = 1 ; i <= n ; i++)
    {
        cin>>a[i],sum[i] = sum[i - 1] + a[i] ;
    }

    // int a, b;
    // while (cin >> a >> b) { // 注意 while 处理多个 case
        // cout << a + b << endl;
    // }
    while (q--)
    {
        int l,r ;
        cin >> l >> r ;
        cout << sum[r] - sum[l - 1] << endl;
    }
}
// 64 位输出请用 printf("%lld")
python 复制代码
#python代码示例
import sys

# for line in sys.stdin:
#     a = line.split()
#     print(int(a[0]) + int(a[1]))


n, q = map(int, input().strip().split())
data = list(map(int, input().strip().split()))
pre = [0 for _ in range(n)]
pre[0] = data[0]
for i in range(1, n):
    pre[i] = pre[i - 1] + data[i]
for i in range(q):
    l, r = map(int, input().strip().split())
    res = pre[r - 1] - pre[l - 1] + data[l - 1]
    print(res)

##二维前缀和

有一个二维数组a和一个二维前缀和数组b,具有以下关系:
b(x),(y) = b(x-1),(y) + b(x),(y-1) + b(x-1),(y-1) + a(x),(y)

说白了每一个格子的值是从哪里得来的,只能从格子的上方和左方得到,但是在更新每个格子的值的时候,我们需要把第1列和第1行的特殊位置进行更新好,第一列的元素值只能从上方传递过来,第一行的元素只能从左边传递过来。

##改进,增加了冗余列和行

#python示例

复制代码
for i in range(len(a)):
    for j in range(len(a[0])):
        if i == 0 and j == 0 :
            b[i][j] = a[i][j]
        if i == 0 : # 第一行
            b[i][j] = b[i][j-1] + a[i][j]
        if j == 0 : # 第一列
            b[i][j] = b[i-1][j] + a[i][j]
        if i != 0 and j != 0 :
            b[i][j] = b[i-1][j] + b[i][j-1] + b[i-1][j-1] + a[i][j]

【模板】二维前缀和_牛客题霸_牛客网 (nowcoder.com)

python 复制代码
#pthon代码示例
while True:
    try:
        n, m, q = map(int, input().split())
        l = []
        for _ in range(n):
            l.append(list(map(int, input().split())))
        # dp[i][j]表示起点到l[i-1][j-1]的子矩阵的和
        dp = [[0 for i in range(m + 1)] for j in range(n + 1)]  # 让dp坐标与x1,y1,x2,y2,对齐 并且添加两个辅助列
        for i in range(1, n + 1):  # 行
            for j in range(1, m + 1):  # 列
                # 状态转移方程,dp[i][j]等于其上方所有行之和加上其左方所有列之和减去其左上方行列交叉导致的减掉双倍区域,再加上本单元格的值
                dp[i][j] = dp[i - 1][j] + dp[i][j - 1] + l[i - 1][j - 1] - dp[i - 1][j - 1]
        print(dp)
        for k in range(q):
            x1, y1, x2, y2 = map(int, input().split())
            # (x1, y1) 为左上角 , (x2,y2) 为右下角的子矩阵的和。x2,y2的值 减去 x1, y1上面的行左边的列,再加上重叠相减的部分
            num = dp[x2][y2] + dp[x1 - 1][y1 - 1] - dp[x1 - 1][y2] - dp[x2][y1 - 1]
            print(num)
    except:
        break
cpp 复制代码
//c++代码示例
#include <iostream>
#include <vector>
using namespace std;

int main() {
    // int a, b;
    // while (cin >> a >> b) { // 注意 while 处理多个 case
    //     cout << a + b << endl;
    // }
    int n,m,q;
    cin>>n>>m>>q ;
    long long tmpv ;
    vector<vector<long long>> v(n+1,vector<long long>(m+1, 0));
    for (int i = 1; i <= n ; i++)
    {
        long long sum = 0 ;
        for (int j = 1 ; j <= m ; j++)
        {
            scanf("%ld",&tmpv) ;
            sum += tmpv ;
            v[i][j] = sum + (i > 1 ? v[i-1][j] : 0) ;
        }
    }
    for (int i = 0 ; i < q ; ++i)
    {
        int x1,y1,x2,y2 ;
        cin>>x1>>y1>>x2>>y2 ;
        cout<<v[x2][y2] - v[x1-1][y2] - v[x2][y1-1] + v[x1-1][y1-1]<<endl;

    }
    return 0 ;
}
// 64 位输出请用 printf("%lld")

#c++代码示例

for (int i = 0 ; i < n ; i++)

{

for (int j = 0 ; j < m ; j++)

{

if (i == 0 && j == 0)

{

b[i][j] = a[i][j] ;

}

if (i == 0)

{

b[i][j] = a[i][j - 1] + a[i][j];

}

if (j == 0)

{

b[i][j] = a[i - 1][j] + a[i][j];

}

if (i != 0 && j != 0)

{

b[i][j] = b[i-1][j] + b[i][j-1] + b[i-1][j-1] + a[i][j] ;

}

}

}

相关推荐
傻啦嘿哟13 分钟前
如何使用 Python 开发一个简单的文本数据转换为 Excel 工具
开发语言·python·excel
B站计算机毕业设计超人19 分钟前
计算机毕业设计SparkStreaming+Kafka旅游推荐系统 旅游景点客流量预测 旅游可视化 旅游大数据 Hive数据仓库 机器学习 深度学习
大数据·数据仓库·hadoop·python·kafka·课程设计·数据可视化
爪哇学长30 分钟前
双指针算法详解:原理、应用场景及代码示例
java·数据结构·算法
爱摸鱼的孔乙己32 分钟前
【数据结构】链表(leetcode)
c语言·数据结构·c++·链表·csdn
风尚云网34 分钟前
风尚云网前端学习:一个简易前端新手友好的HTML5页面布局与样式设计
前端·css·学习·html·html5·风尚云网
Dola_Pan34 分钟前
C语言:数组转换指针的时机
c语言·开发语言·算法
IT古董43 分钟前
【人工智能】Python在机器学习与人工智能中的应用
开发语言·人工智能·python·机器学习
繁依Fanyi1 小时前
简易安卓句分器实现
java·服务器·开发语言·算法·eclipse
烦躁的大鼻嘎1 小时前
模拟算法实例讲解:从理论到实践的编程之旅
数据结构·c++·算法·leetcode
IU宝1 小时前
C/C++内存管理
java·c语言·c++