一维差分
前置知识:差分数组
差分数组就是原始数组相邻元素之间的差
性质:
1、当它在某个区间加上一个值的时候,它的差分数组只会改变两个值,一个是区间的左端点,一个是区间的右端点的后一个值。(此时注意包含端点时,只会改变一个数据 )
例如:区间[L,R]+k
d[L]=d[L]+k d[R+1]=d[R+1]-k
2、原始数组等于上一个数组加上当前差分数组
即:a[i]=a[i-1]+d[i]
3、对于a[x]=d[1]+d[2]+……+d[x]
用法:
1、在一些求和的子问题,可以把a看作全是0的数组然后进行+
2、在一些问题可以利用差分只改变两项与只改变一项的思想,也可以用
例如:空调问题
题目要求同时将一段子数组全部加上1或者减去1, 直觉上就考虑采用差分数组的思想, 将原数组每一项的原始温度减去目标温度得到数组a, 得到每一项需要改变的数值, 然后求出a数组的差分数组b,当数组a为0时,差分数组b也为0,说明没有需要改变的数值了,所以目标是使得差分数组b的每一项变成0,
我们的操作方式有2种:(对于b)
选择任意两项, 一项加1, 另一项减1(不包含端点操作)
选择任意一项 加1 或者 减1(对a,包含端点操作)
从头开始,让他为0,(只用选择任意一项+1,或者-1,用两个数±次数保存)
显然, 使数组全部变为0的最少操作方案就是 差分数组中负数和的绝对值,正数之和的之间的最大值
此问题说明了,只要一个序列变成另一个序列都可以考虑差分
#include<iostream>
using namespace std;
const int N=1e5+10;
int f[N];//初始
int e[N];//目标
int d[N];//差分
int num1;
int num2;
int n;
int main()
{
cin>>n;
for(int i=1;i<=n;i++) {cin>>e[i];}
for(int i=1;i<=n;i++) {cin>>f[i];d[i]=f[i]-e[i];}
for(int i=1;i<=n;i++)
{
int s=d[i]-d[i-1];
if(s>0) num1+=s;
else num2-=s;
}
cout<<max(num1,num2)<<endl;
return 0;
}