前缀和和差分(1维)
1.一维前缀和
目的:
设有一n项数组a,求
调用时只用O(1),预处理O(n)
做法:
1.定义数组pre,
这样就可以计算了:如:l=4,r=6
PS:是pre[r]-pre[l+1]
是pre[r]-pre[l+1]
是pre[r]-pre[l+1]
重要的事情说三遍
Problem
求
要O(i)-->就算是O(n)
那球 pre 就要……
那还是不满足要求
那……
pre[i]=pre[i-1]+a[i]
后缀和
用法:见后文
rsum存值的伪代码:
for(i=n~1) rsum[i]=rsum[i+1]+a[i]
Description
需要实现一个可以快速求数列区间和的程序,你也来试试吧!
Format
Input
第一行输入两个正整数 n(1<n<
)和 m(1<m <
)。
第二行连续输入 nn个 int 型整数,用 1 个空格隔开。
接着连续 m 行,每行两个正整数 x,y,用 1 个空格隔开,表示一次询问,[x,y] 区间内的元素和是多少。
Output
输出共 m 行,每行 1 个整数,表示该数列在对应区间 [x,y] 范围内的元素之和(保证在long long 的范围内)。
Samples
输入数据 1
5 3 9 1 2 0 6 2 4 1 3 2 5
输出数据 1
3 12 9
伪代码:
//只写main
输入
for(i=1~n) pre[i]=pre[i-1]+a[i];
for(i=1~m){输入输出pre[r]-pre[l-1]
}
#include <cstdio>
const int N=1e6+7;
long long a[N];
int main(){int n,m;scanf("%d%d",&n,&m);for(int i=1;i<=n;++i){scanf("%lld",a+i);a[i]+=a[i-1];}for (int i=1,l,r;i<=m;++i){scanf("%d%d",&l,&r);printf("%lld\n",a[r]-a[l-1]);}return 0;
}
此代码a直接pre用了
注意点(我原来没过的原因):
1).long long的问题
2).n,m<,不能用 cin & cout
以为前缀和的就这么简单?NO,魅力无穷!
这只是基本运用!
再来看一道题目
轩轩和凯凯正在玩一款叫《龙虎斗》的游戏,游戏的棋盘是一条线段,线段上有 n 个兵营(自左至右编号
,相邻编号的兵营之间相隔 1 厘米,即棋盘为长度为 n-1 厘米的线段。i 号兵营里有 位工兵。 下图为 n=6 的示例:
轩轩在左侧,代表“龙”;凯凯在右侧,代表“虎”。 他们以 m 号兵营作为分界, 靠左的工兵属于龙势力,靠右的工兵属于虎势力,而第 m 号兵营中的工兵很纠结,他们不属于任何一方。
一个兵营的气势为:该兵营中的工兵数= 该兵营到
m 号兵营的距离;参与游戏 一方的势力定义为:属于这一方所有兵营的气势之和。下图为n=6,m=4 的示例,其中红色为龙方,黄色为虎方:
设 m=4 :
龙:
虎:
现在告诉你每一个兵营的工兵数量,请你设定分界兵营,使龙虎的总战斗力差值最小。请求出这个差值。
【输入格式】
第一行一个整数 n。
第二行 n 个整数
【输出格式】
一个整数表示答案。
【输入输出样例#1】
输入#1
5 1 2 3 4 5
输出#1
5
【输入输出样例#2】
输入#2
10 1 7 5 4 2 3 5 7 8 9
输出#2
21
【数据范围】
对于 100% 数据:1
n
,
。
一看,一个字:“懵”,没思路啊!
注释:
此处pre与ls的意思一样思路:
龙:
懂了吧!
虎和前缀和一样的意思,此处不展示
然后还是
啊
对了,定一个数组是前缀和的前缀和就ok了,(还有后缀和的后缀和)
其实这题可以只用一次前缀和&后缀和,是定义l=0,r=
然后每次 l+
,r-
,此处就不展示了
#include <bits/stdc++.h>
using namespace std;
#define N 101000
#define int long long
int n,val[N],ls[N],rs[N],lss[N],rss[N];
signed main() {cin>>n;for(int i=1;i<=n;++i) cin>>val[i];for(int i=1;i<=n;++i) ls[i]=ls[i-1]+val[i];for(int i=n;i>=1;--i) rs[i]=rs[i+1]+val[i];for(int i=1;i<=n;++i) lss[i]=lss[i-1]+ls[i];for(int i=n;i>=1;--i) rss[i]=rss[i+1]+rs[i];int ans=1e18;for(int i=1;i<=n;++i)ans=min(ans,abs(lss[i-1]-rss[i+1]));cout<<ans;return 0;
}
现在前缀和也知道了,后缀和也知道了,把前缀积与后缀积说一下
储存方法
前缀积
pre[0]=1;//重中之重,否则全0
for(i=1~n) pre[i]=pre[i-1]*a[i];
后缀积
rs[n+1]=1//重中之重,否则全0
for(i=n~1) rs[i]=rs[i+1]*a[i];
2.差分
目标:
每个值都加 x
调用O(1),最后加一个O(n)
很玄幻的东西,做法
1.每次 s[l]+=x,s[r+1]-=x
2.做前缀和
记得要加上原来的值
但别原来在a上改,因为要做前缀和
这个不难,就放一道例题
Background
学会了前缀和以后,小 J 想通过前缀和算法解锁一些新技能。
现在,他想对一个整数序列进行一系列的区间加减,求出调整后的序列。
Description
例如:对于 5 个元素的序列 9 1 2 5 3,将 [2, 4] 区间的所有数都加上 2,再将 [1, 4] 区间的所有数加上 5,再将 [4, 5] 区间的所有数减去 2,得到的序列是14 8 9 10 1。
这样的代码该怎么写呢?
Format
Input
第一行输入两个正整数 n(
),m(
)。
第二行连续输入 nn 个整数。
接下来连续输入 m 行,每行 3 个整数 l,r,x(0<l≤r≤n,
),表示对 [l,r] 区间的所有数都加上一个 x。
Output
输出 1 行 n个整数,是经过调整后的序列。
Samples
输入数据
5 3 9 1 2 5 3 2 4 2 1 4 5 4 5 -2
输出数据
14 8 9 10 1
#include <bits/stdc++.h>
using namespace std;
const int N=1e6+7;
typedef long long ll;
ll a[N],s[N],pre[N];
int main(){int n,m;cin>>n>>m;for(int i=1;i<=n;++i)scanf("%d",a+i);for (int i=1,a,b,c;i<=m;++i){scanf("%d%d%d",&a,&b,&c);s[a]=c,s[b+1]=-c;//差分}for(int i=1;i<=n;++i){pre[i]=pre[i-1]+s[i];a[i]+=pre[i];//前缀和}for(int i=1;i<=n;++i) printf("%d ",a[i]);return 0;
}
前缀和和差分(1维)相关推荐
- 前缀和,差分算法训练
知识点: 一维前缀和 二维前缀和 一维差分 二维差分 题目: 蓝桥杯2017初赛-k倍区间-前缀和 [蓝桥杯2018初赛]递增三元组-双指针,枚举,排序,前缀和
- 基本算法——前缀和与差分
一.前缀和 一维前缀和 顾名思义,不再赘述. #include <iostream> #include <cstdio> #include <algorithm> ...
- 前缀和与差分那些不得不说的事(一维,二维)公式与图解详细解说
前言: 最近实验室的小伙伴们都开始学习前缀和和差分了呢,阿皓也发现这两个东西确实是不容易理解啊.尤其是那个二维差分,很容易跟别的东西弄混,甚至有些同学们现在还不知道二维差分是个什么东东.所以呢,阿皓就 ...
- 前缀和、二维前缀和与差分的小总结
在了解二维前缀和之前,我们首先需要了解一下什么是前缀和. 如果我给你一串长度为n的数列a1,a2,a3......an,再给出m个询问,每次询问给出L,R两个数,要求给出区间[L,R]里的数的和,你会 ...
- [动态差分+二维前缀和][小a的轰炸游戏]
链接:https://ac.nowcoder.com/acm/contest/317/E 来源:牛客网 题目描述 小a正在玩一款即时战略游戏,现在他要用航空母舰对敌方阵地进行轰炸 地方阵地可以看做是n ...
- 0x03.基本算法 — 前缀和与差分
目录 一.前缀和 二.二维前缀和 1.二维前缀和的修改和求和 0. NOI 2003激光炸弹(二维前缀和) 1.牛妹吃豆子(二维前缀和模板,修改+求和) 2.静态数组的区间求和问题 3.静态维护区间加 ...
- 基本算法之前缀和与差分的是使用
前缀和与差分 前缀和 鸣谢 二维前缀和 激光炸弹 差分 求差分 差分求区间修改 增减序列 最高的牛 前缀和 鸣谢 添加链接描述 和 添加链接描述 二维前缀和 激光炸弹 题目链接 解题思路: 解法思路: ...
- 第四章:前缀和、差分(数列)
前缀和差分 一.前缀和 1. 什么是前缀和 2. 前缀和的作用 3. 前缀和的例题和模板 (1)一维数组的前缀和 C++版 C版 (2)二维数组的前缀和 a.思路: b.题目和模板: C++版 C版 ...
- c++算法基础必刷题目——前缀和与差分
文章目录 前缀和与差分算法: 1.校门外的树 2.值周 3.中位数图 4.激光炸弹 5.二分 6.货仓选址 前缀和与差分算法: 前缀和与差分算法主要是为了快速求出某个区间的和,例如有一个数组a[1 ...
- 线性结构-前缀和和差分
主要内容: [概述] [一维前缀和] [二维前缀和] [例题] [差分数组]
最新文章
- SQL Server 事务、异常和游标
- 简单的python抢红包脚本-这个Python脚本牛逼了,秒抢红包就算了,还能无视撤回消息...
- Python list 操作
- opencv的基本数据结构(一)(转)
- python中的tkinter模块
- mysql存储过程局部变量使用_MySQL存储过程使用输出变量
- Linux系统服务及其创建详解(service/chkconfig)
- linux没有找到可用磁盘,在Linux上,有没有一种更像python的方法来获取可用磁盘设备名的列表?...
- ThinkPhp 使用 PHP_XLSXWriter 代替 PHPExcel 百万级数据单次导出
- textjoin去重_Excel 2016新增函数之TEXTJOIN
- Windows远程桌面如何设置分辨率
- 计算机中及格人数怎么算,在excel中如何计算及格率和优秀率及统计各分数段人数...
- python中的乘方_python乘方运算
- 值得一生收藏的经典台词
- 计算机网络dce是什么意思,DTE与DCE的解释
- Jmeter性能测试-插件
- 阿里云思维导图系列(五)阿里云关系型数据库产品全家福
- Kettle使用笔记
- Java Exer0908 从键盘输入皆为正整数的数组元素,数组长度不确定,请找出数组中重复的数字并输出。
- SunJDK的历史转折点
热门文章
- C#学生成绩管理系统
- android v7支持库使用,正确引用 Android Support v7 兼容支持库
- 工科试验班 计算机类,什么是工科试验班??
- 徐州教育局派调查组进驻“华夏学宫”展开调查
- Docker学习笔记3
- Windows10从1909升级21H1到31%卡住解决方法
- 基于python + opencv的视频播放调节功能
- java 前端和后端_java编程语言是前端还是后端
- 浅析即时通讯开发之移动端实时音视频直播技术编码和封装
- openpyxl修改图表中纯色填充的透明度和颜色