每周一算法:差分算法

news/2024/11/20 0:42:40/

差分算法

差分是一种常见的算法,用于快速修改数组中某一段区间的值。其基本思想就是预处理出数组的差分数组,然后修改区间时,只需要修改两个位置的值,即可快速完成区间修改。最后再通过差分数组求出原数组。差分算法在区间加、区间求和等问题中都有广泛的应用。

算法思想

  • 在原序列的基础上构造差分数组 d [ ] d[] d[],其中 d [ i ] d[i] d[i]表示序列中相邻两个元素之间的差值,即 d [ i ] = A [ i ] − A [ i − 1 ] d[i]=A[i]-A[i-1] d[i]=A[i]A[i1]。例如:对于序列 A = ( 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ) A=(0,0,0,0,0,0,0,0,0,0) A=(0,0,0,0,0,0,0,0,0,0)的差分数组 d [ ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } d[]=\{0,0,0,0,0,0,0,0,0,0\} d[]={0,0,0,0,0,0,0,0,0,0}
    在这里插入图片描述

  • 在修改区间时,只需要更新差分数组两个位置上的值,即可快速完成修改。例如:给区间 [ L , R ] [L,R] [L,R]的元素加上 k k k,那么只需要将差分数组 d [ L ] + = k d[L] += k d[L]+=k d [ R + 1 ] − = k d[R + 1]-=k d[R+1]=k即可。例如:对序列 A A A的区间 [ 2 , 5 ] [2,5] [2,5]每个数增加 3 3 3,则将差分数组 d [ 2 ] + = 3 , d [ 6 ] − = 3 d[2]+=3,d[6]-=3 d[2]+=3,d[6]=3即可;对序列 A A A的区间 [ 1 , 7 ] [1,7] [1,7]每个数增加 2 2 2,则将差分数组 d [ 1 ] + = 2 , d [ 8 ] − = 2 d[1]+=2,d[8]-=2 d[1]+=2,d[8]=2即可;
    在这里插入图片描述

  • 最后,通过对差分数组计算前缀和来还原出更新之后的序列。
    在这里插入图片描述

时间复杂度

前缀和算法的时间复杂度分为两部分:

  • 对原序列的区间增加值: O ( 1 ) O(1) O(1)
  • 对差分数组求前缀和: O ( n ) O(n) O(n)

代码模板

//构造差分数组
void add(int L, int R, int k) 
{d[L] += k;d[R + 1] -= k;
}
//对差分数组求前缀和,还原序列
for(int i = 1; i <= n; i ++)d[i] += d[i - 1];

真题演练

题目链接:山东CSP-J2022 入门组1

有一排树苗,编号依次是 0 , 1 , 2 , . . . 0,1,2,... 012...。现有 n n n个志愿者去给树苗浇水,第 i i i个志愿者选定了一个区间 [ a i , b i ] [a_i,b_i] [aibi],表示第 i i i个志愿者将 [ a i , b i ] [a_i,b_i] [aibi]这一区间内的每一棵树都浇一次水。

如某个志愿者选择的浇水区间为 [ 4 , 9 ] [4,9] [49],表示他将给编号为 4 , 5 , 6 , 7 , 8 , 9 4,5,6,7,8,9 456789的树各浇水一次。

当所有的志愿者完成各自所选区间的浇水后,可能有些树苗被不同的志愿者浇力多次,也可能有的树苗一次也没被浇过水。

请你求出浇水最多的树苗被浇了多少次。

输入格式

第1行,一个整数 n n n,表示志愿者的人数。

第2行到第 n + 1 n+1 n+1行,每行两个整数 a , b i ( i = 0 , 1 , 2 , . . . n − 1 ) a_,b_i(i=0,1,2,...n-1) abii=012...n1,表示志愿者i选择的浇水区间。

输出格式

输出1行, 1 1 1个整数,表示浇水最多的树苗被浇水的次数。

样例输入

4
0 2
2 4
1 4
6 7

样例输出

3

提示

对于所有的数据: n < 1 0 5 n<10^5 n<105 0 < a < b < 1 0 6 0<a<b<10^6 0<a<b<106

解题思路

根据题目描述有 n n n个志愿者去给树苗浇水,每个志愿者将 [ a i , b i ] [a_i,b_i] [aibi]这一区间内的每一棵树都浇一次水,求浇水最多的树苗被浇了多少次。那么:

  • 可以用数组 d [ ] d[] d[]表示每个位置的浇水次数, d [ ] d[] d[]初始化为 0 0 0.
  • 每次对区间 [ L , R ] [L,R] [L,R]浇水时,将差分数组 d [ L ] + = 1 , d [ R + 1 ] − = 1 d[L] +=1,d[R + 1]-=1 d[L]+=1,d[R+1]=1
  • 最后对差分数组求前缀和得到每棵树苗的浇水次数,并求出其中的最大值。

代码实现

#include <iostream>
using namespace std;
const int N = 1e6 + 10;
int d[N]; //差分数组
int main()
{int n, m = 0;scanf("%d", &n);for(int i = 1; i <= n; i ++){int L, R;scanf("%d%d", &L, &R);d[L] += 1, d[R + 1] -= 1;m = max(m, R);}int ans = 0;for(int i = 0; i <= m; i ++){if(i > 0) d[i] += d[i - 1];ans = max(ans, d[i]);}cout << ans << endl;
}

总结

  • 差分算法可以快速修改序列中某一段连续区间的值。过程如下:
    • 在原序列的基础上构造差分数组
    • 给区间 [ L , R ] [L,R] [L,R]的元素加上 k k k,那么只需要将差分数组 d [ L ] + = k d[L] += k d[L]+=k d [ R + 1 ] − = k d[R + 1]-=k d[R+1]=k
    • 对差分数组计算前缀和来还原出更新之后的序列。
  • 除此之外,差分的思想还可以扩展到二位数组中。

http://www.ppmy.cn/news/66818.html

相关文章

小米刷机小白教程最新详细版

★本篇为线刷&#xff08;以修补boot的方式刷入面具&#xff09; 如果你用的是小米手机&#xff0c;想获取面具root&#xff0c;看这一篇就够了&#xff0c;即使你是小白 必应搜索醉里博客http://202271.xyz?xiaomi 原创不易&#xff0c;谢绝转载&#xff0c;如果本教程有帮…

git 解决 “fatal: Could not read from remote repository.“

现象 在使用Git将本地仓库推送到远程仓库的时候&#xff0c;发生了如下错误&#xff1a;“fatal: Could not read from remote repository.” 原因 出现这错误一般是以下两种原因&#xff1a; 客户端与服务端未生成 ssh key客户端与服务端的ssh key不匹配 为解决以上问题&a…

【AI大模型智慧办公】用《文心一言》1分钟写一篇博客简直yyds

文章目录 前言文心一言是什么文心一言可以做什么文心一言写博客申请体验写在最后 前言 当今社会&#xff0c;博客已成为了许多人分享观点、知识和经验的重要平台。用文心一言写博客是将自己的思考、想法和经验以文字的形式呈现出来&#xff0c;让更多人了解自己。通过写博客&a…

BRC20科普——关于Brc20的相关问题

统一回答下新人最近遇到的问题&#xff01; 1&#xff0c;brc20的铭文与代币什么关系&#xff1f; 答&#xff1a; 铭文相当于一个袋子&#xff0c;里面装着Token。 每个brc20Token的铸造都有指定的名字与固定数量&#xff0c;例如odri&#xff08;Token名称&#xff09;&am…

Figma中文网?比Figma更懂你的设计网站!

一个比 Figma 更懂你的设计网站的 Figma 中文网 —— 即时设计是一个非常有用的设计资源平台&#xff0c;它提供了大量的免费设计素材&#xff0c;包括来自各大厂商的 UI 组件库、精美的模板、插画设计和矢量图标素材等等。设计师可以从中学习到大师的设计技巧和规范&#xff0…

环评制图丨最新导则下的生态系统、土地利用、植被覆盖、适宜生境分布图等制图

根据最新生态环境影响评价导则&#xff0c;结合生态环评内容庞杂、综合性强的特点&#xff0c;以既包括陆域、又包括水域的项目为主要案例&#xff0c;对生态环评的具体流程及所需内容进行系统阐述。利用Rstudio、Fragstats等软件分析计算生态环评中所需各种指数&#xff0c;利…

摄像头接口标准

UVC&#xff08;USB Video Class&#xff09;&#xff1a;UVC是一种通用的USB摄像头接口标准&#xff0c;使得摄像头设备能够与各种操作系统兼容&#xff0c;实现即插即用的功能。 CSI&#xff08;Camera Serial Interface&#xff09;&#xff1a;CSI是一种串行摄像头接口&am…

python进程池

锁 死锁&#xff1a;两个或者两个以上的线程或者进程在执行中&#xff0c;因为资源竞争出现相互等待的情况。导致程序进入阻塞的状态。 递归锁&#xff1a;可以一次加多个锁 from threading import Thread , RLock g 0 def func():for i in range(100):global gg 1print(…