一般来说差分的函数是这样的
void batch_add(int l,int r,int num)
{
b[l]+=num;
b[r+1]-=num;
}
int main()
{
//假设原数组a[N];
for(int i = 1;i<=n;i++)
{
batch_add(1,1,a[i]);
}
}
那原理是什么
b[1]=a[1];
b[2]=a[2]-a[1];
b[3]=a[3]-a[2];
.....
b[n]=a[n]-a[n-1];
b[n+1]=-a[n];
由此可见得到差分的两个性质:
a[n]=b[1]+b[2]...+b[n];
b[1]+b[2]+...+b[n+1]=0;
有什么用处
//对区间进行加减法
比如a[5]={1,2,3,-1,2};
要使0-3同时加1;
就可以使b[0]+1,b[3+1]-1;
为什么?
当b[0]+1时候: a[0]=b[0];a[1]=b[0]+b[1];...a[3]=b[0]+b[1]+b[2]+b[3];
然后到b[4]时候1又被减去,这就是差分的概念
差分的高阶运用比如AcWing网站这道题目考了差分的高阶运用
也是对于区间来加减的,如果我们直接去求,我们可能选择一个一个来调节,或者同将同大同小的一起调节,很难想到把他们一起处理。
这时候我们可以运用差分来解决这个问题
5
理想1 5 3 3 4
现实1 2 2 2 1
我们就可以直接记录它们的差值来做差分
得到 0 -3 -1 -1 -3
进行差分 0 -3 2 0 -2 3
这样来看我们就可以根据b[l]+=1;b[r+1]-=1;这个概念选择一个正数和负数来进行加减
最后可以看到其实正数和是等于负数和的绝对值的,而一次操作一度,那么显然,我们的正数和就是操作的次数。
直接上代码
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
int n;
int p[N],t,b[N];
void batch_add(int l,int r,int num)
{
b[l]+=num;
b[r+1]-=num;
}
int main()
{
scanf("%d",&n);
for(int i = 1;i<=n;i++)
{
scanf("%d",&p[i]);
}
for(int i = 1;i<=n;i++)
{
scanf("%d",&t);
p[i]-=t;
}
for(int i = 1;i<=n;i++)
{
batch_add(i,i,p[i]);
}
int sum=0;
for(int i = 1;i<=n+1;i++){
if(b[i]>0)
sum+=b[i];
}
printf("%d",sum);
return 0;
}