前缀和与差分

目录

一、前缀和算法

1. 什么是前缀和

2. 一维前缀和

3.二维前缀和

4.前缀和的应用场景

二、差分算法

1.什么是差分

2. 一维差分

3.二维差分

4.差分的应用场景

三、总结


前缀和与差分是算法竞赛和面试中经常遇到的两种重要技巧,它们能够有效地优化某些特定类型问题的求解效率。本文将详细介绍这两种算法的概念、实现方法以及典型应用场景。

一、前缀和算法

1. 什么是前缀和

前缀和是一种对数组进行预处理的技术,它能够在O(1)时间内求出数组中任意区间的和。其核心思想是预先计算并存储数组从起始位置到每个位置的和。例如,原数组 [1, 2, 3, 4] 的前缀和数组为 [0, 1, 3, 6, 10](假设下标从 1 开始)。

2. 一维前缀和

对于一个数组a,其前缀和数组定义为:

s[0] = 0

s[i] = s[i-1] + a[i](i >= 1)

代码实现:

int n;
cin >> n;
int a[n+5]; 
int sum[n+5]; 
sum[0] = 0; 
for (int i = 1; i <= n; i++) 
{
    cin >> a[i];  
    sum[i] = sum[i-1] + a[i];
}

查询区间和:

要查询原数组a中区间[l, r]的和(假设下标从1开始),可以使用:

sum = s[r] - s[l-1]

3.二维前缀和

定义:

s[i][j]表示从(1,1)到(i,j)形成的矩形区域的和。

递推公式:

s[i][j] = s[i-1][j] + s[i][j-1] - s[i-1][j-1] + a[i][j]

查询子矩阵和:

对于矩形区域(x1,y1)到(x2,y2)的和:

sum = s[x2][y2] - s[x1-1][y2] - s[x2][y1-1] + s[x1-1][y1-1]

 代码示例:

int n, m;
cin >> n >> m;
int a[n+1][m+1], sum[n+1][m+1];
for (int i = 1; i <= n; i++) 
{
    for (int j = 1; j <= m; j++) 
    {
        cin >> a[i][j];
        sum[i][j] = sum[i-1][j] + sum[i][j-1] - sum[i-1][j-1] + a[i][j];
    }
}

4.前缀和的应用场景

1. 频繁查询数组某个区间的和

2. 解决某些子数组问题(如和为k的最长子数组)

3. 二维情况下的子矩阵求和问题

4. 优化某些动态规划问题

二、差分算法

1.什么是差分

差分是前缀和的逆运算,它主要用于对数组的某个区间进行快速增减操作。

2. 一维差分

定义:

对于原数组a,其差分数组d定义为:

d[1] = a[1]

d[i] = a[i] - a[i-1](i > 1)

代码实现:

int n;
cin >> n;
int a[n+5], d[n+5];
a[0] = 0; 
for (int i = 1; i <= n; i++) 
{
    cin >> a[i];
    d[i] = a[i] - a[i-1];
}

1.区间增减操作:

   对原数组a的区间[l, r]中的每个元素增加c:

   d[l] += c

   d[r+1] -= c (如果r+1在数组范围内)

2.恢复原数组:

   通过对差分数组求前缀和即可得到原数组。

3.二维差分

定义:

对于二维数组a[i][j],其差分数组d[i][j]满足:

d[i][j] = a[i][j]-a[i-1][j]-a[i][j-1]+a[i-1][j-1]

子矩阵增减操作:

要对子矩阵(x1,y1)到(x2,y2)中的每个元素增加c:

d[x1][y1] += c

d[x1][y2+1] -= c

d[x2+1][y1] -= c

d[x2+1][y2+1] += c

4.差分的应用场景

1. 频繁对数组某个区间进行增减操作

2. 区间调度问题

3. 二维情况下的子矩阵增减操作

三、总结

前缀和和差分是两种非常实用的算法技巧, 前缀和适用于频繁查询区间和的场景,差分适用于频繁修改区间的场景。两者可以相互转换,互为逆运算。掌握这两种技巧非常有必要噢。

接下来还需要例题来巩固理解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值