前缀和与差分
第一讲 前缀和与差分
听讲人:24级算法组小萌新
卑微讲题人:22049212-梁军斌(本人正在疯狂整理入党材料中)
我认为,每个人最重要的不是过去,而是现在;虽然背负着昨日的重担,但也有自己想要追寻的东西。
希望你从今以后无论去往何处都不要忘记,世界上有那么多爱你的人。
你道你机关算尽,可你真算到了自己也要下场当棋子吗?
坐看日月行,细数千帆过。
年年今日,灯明如昼。原火不灭,愿人依旧。
先来看一道例题
题目描述
给定一个长度为
对于每个询问,需要计算并输出原序列中从第
输入格式
- 第一行包含两个整数
和 。 - 第二行包含
个整数,表示整数数列。 - 接下来
行,每行包含两个整数 和 ,表示一个询问的区间范围。
输出格式
- 共
行,每行输出一个询问的结果。
数据范围
数列中元素的值
示例
输入样例
5 3
2 1 3 6 4
1 2
1 3
2 4
输出样例
3
6
10
参考代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
using i64 = long long;
const int N = 3e5+10;
void solve()
{
int n,m;
cin>>n>>m;
vector<int> a(n+1,0);
for(int i=1;i<=n;i++) cin>>a[i];
vector<int> s(n+1,0);
for(int i=1;i<=n;i++) s[i]=s[i-1]+a[i];
while(m--)
{
int l,r;
cin>>l>>r;
cout<<s[r]-s[l-1]<<endl;
}
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
int _=1;
//cin>>_;
while(_--)
{
solve();
}
}
前缀和
定义
前缀和可以简单理解为「数列的前
std::partial_sum
,定义于头文件 <numeric>
中。
设数列的前
-
已知一个长度为
的数组 : -
= -
= + -
= + + -
-
= + + + + -
= + + + + +
知道前缀和,便可以知道任意区间内所有数之和,即
= + + + + = + + + + + = + + + + = - ;
例:
= - = - = -
如何求前缀和?
首先初始化
a[0]=0;
for(int i = 1;i <= n;i ++)
{
a[i]+=a[i-1];
// s[i]=s[i-1]+a[i];
}
二维前缀和
基于容斥原理
这种方法多用于二维前缀和的情形。给定大小为
类比一维的情形,
实现时,直接遍历
考虑一个具体的例子。
这里,
同样的道理,在已经预处理出二位前缀和后,要查询左上角为
这可以在
在二维的情形,以上算法的时间复杂度可以简单认为是
逐维前缀和
对于一般的情形,给定
从上式可以看出,
树上前缀和
设
然后:
-
若是点权,
路径上的和为 。 -
若是边权,
路径上的和为 。LCA 的求法参见 最近公共祖先。
题目描述
给定一个
对于每个询问,输出该子矩阵中所有数的和。
输入格式
- 第一行包含三个整数
, , 。 - 接下来的
行,每行包含 个整数,表示整数矩阵。 - 接下来
行,每行包含四个整数 ,表示一组询问。
输出格式
共
数据范围
矩阵内元素的值
输入样例
3 4 3
1 7 2 4
3 6 2 8
2 1 2 3
1 1 2 2
2 1 3 4
1 3 3 4
输出样例
17
27
21
参考代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1010;
typedef long long ll;
int a[N][N];
int s[N][N];
int n,m,q;
int main()
{
cin>>n>>m>>q;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>a[i][j],s[i][j]=0;
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]+a[i][j]-s[i-1][j-1];
}
}
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;
}
}
差分
解释
差分是一种和前缀和相对的策略,可以当做是求和的逆运算。
这种策略的定义是令
性质
的值是 的前缀和,即- 计算
的前缀和
它可以维护多次对序列的一个区间加上一个数,并在最后询问某一位的数或是多次询问某一位的数。注意修改操作一定要在查询操作之前。
譬如使
其中
最后做一遍前缀和就好了。
C++ 标准库中实现了差分函数 std::adjacent_difference
,定义于头文件 <numeric>
中。
题目描述
输入一个长度为
接下来输入
请你输出进行完所有操作后的序列。
输入格式
- 第一行包含两个整数
和 。 - 第二行包含
个整数,表示整数序列。 - 接下来
行,每行包含三个整数 ,表示一个操作。
输出格式
共一行,包含
数据范围
整数序列中元素的值
输入样例
6 3
1 2 2 1 2 1
1 3 1
3 5 1
1 6 1
输出样例
3 4 5 3 4 2
参考代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,m;
cin>>n>>m;
vector<int> a(n+1,0);
vector<int> b(n+1,0);
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++) b[i]=a[i]-a[i-1];
while(m--)
{
int l,r,c;
cin>>l>>r>>c;
b[r+1]-=c;
b[l]+=c;
}
for(int i=1;i<=n;i++) b[i]+=b[i-1];
for(int i=1;i<=n;i++) cout<<b[i]<<" \n"[i==n];
}
二维差分
题目描述
输入一个
每个操作都要将选中的子矩阵中的每个元素的值加上
请你将进行完所有操作后的矩阵输出。
输入格式
- 第一行包含整数
。 - 接下来
行,每行包含 个整数,表示整数矩阵。 - 接下来
行,每行包含 5 个整数 ,表示一个操作。
输出格式
共
数据范围
矩阵内元素的值
输入样例
3 4 3
1 2 2 1
3 2 2 1
1 1 1 1
1 1 2 2 1
1 3 2 3 2
3 1 3 4 1
输出样例
2 3 4 1
4 3 4 1
2 2 2 2
参考代码:
#include<bits/stdc++.h>
using namespace std;
int a[1010][1010];
int b[1010][1010];
int n,m,q;
int main()
{
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++)
{
b[i][j]=a[i][j]-a[i-1][j]-a[i][j-1]+a[i-1][j-1];
}
}
while(q--)
{
int x1,y1,x2,y2,c;
cin>>x1>>y1>>x2>>y2>>c;
b[x1][y1]+=c;
b[x2+1][y1]-=c;
b[x1][y2+1]-=c;
b[x2+1][y2+1]+=c;
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
a[i][j]=a[i-1][j]+a[i][j-1]-a[i-1][j-1]+b[i][j];
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
cout<<a[i][j]<<" \n"[j==m];
}
}
习题
前缀和:
- 洛谷 B3612【深进 1. 例 1】求区间和
- 洛谷 U69096 前缀和的逆
- AtCoder joi2007ho_a 最大の和
- 「USACO16JAN」子共七 Subsequences Summing to Sevens
- 「USACO05JAN」Moo Volume S
二维/多维前缀和:
- HDU 6514 Monitor
- 洛谷 P1387 最大正方形
- 「HNOI2003」激光炸弹
- CF 165E Compatible Numbers
- CF 383E Vowels
- ARC 100C Or Plus Max
树上前缀和:
差分:
树上差分:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效