前言:
好几个星期前学的,逐渐淡忘了,今日再次遇见,专门写一篇博客介绍很好用的一个算法–差分
概述:
差分算法适用于区间加减一个数,是前缀和的逆运算,二者经常出现在同一题目。
同时差分和前缀和一样分为一维差分与二维差分,下面将用题目带大家了解差分
实践:
一维差分
一维差分核心公式
1 2
| a[l]+=w;//注意是对差分数组进行操作 a[r+1]-=w;
|
小明拥有N个彩灯,第i个彩灯的初始亮度为ai。
小明将进行Q次操作,每次操作可选择一段区间,并使区间内彩灯的亮度+x(x可能为负数)。
求Q次操作后每一个彩灯的亮度(若彩灯亮度为负数则输出为0)
代码实现: 差分+前缀和
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| using namespace std; const int N=1e5; int s[N],a[N]; void insert(int l,int r,int w)//进行差分,使得区间加减w { a[l]+=w; a[r+1]-=w;
} int main() { int n,q; cin>>n>>q; for(int i=1;i<=n;i++)cin >>s[i]; for(int i=1;i<=n;i++)insert(i,i,s[i]);//获得差分数组 while(q--)//进行操作 { int l,r,w; cin>>l>>r>>w; insert(l,r,w); } for(int i=1;i<=n;i++)//进行前缀和 a[i]+=a[i-1]; for(int i=1;i<=n;i++) { if(a[i]<=0)cout<<0<<' '; else cout<<a[i]<<' '; } return 0; }
|
二维差分
二维差分核心公式
1 2 3 4
| b[x1][y1]+=1; b[x2+1][y1]-=1; b[x1][y2+1]-=1; b[x2+1][y2+1]+=1;
|
题解:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| using namespace std; const int N=1005,M=1005; int b[N][N]; void insert(int x1,int y1,int x2,int y2) { b[x1][y1]+=1; b[x2+1][y1]-=1; b[x1][y2+1]-=1; b[x2+1][y2+1]+=1; } int main() { int n,m; cin>>n>>m; while(m--) { int x1,y1,x2,y2; cin>>x1>>y1>>x2>>y2; insert(x1,y1,x2,y2); } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { b[i][j]+=b[i-1][j]+b[i][j-1]-b[i-1][j-1]; } for(int i=1;i<=n;i++) { for (int j = 1; j <= n; j++) cout << b[i][j] << ' '; cout<<endl; }
return 0; }
|