Luogu P3397 地毯
Luogu P3397 地毯
一道二维差分的板子题。
因为二维差分比起一维的来说并不那么直观,所以这里主要讲一下二维差分的实现思路。
首先,记二维前缀和为
显然,
这里,我们要用到一个性质:差分的前缀和为原数,即
则代入二维前缀和的递推式,可以得到二维差分满足的关系式:
变形一下得到二维差分的计算式:
最后我们再来考虑如何实现题目中,修改一个左上角是
类比前缀和的计算,不难得到:
-
D_{x_1,y_1} \gets D_{x_1,y_1}+1 -
D_{x_1,y_2+1} \gets D_{x_1,y_2+1}-1 -
D_{x_2+1,y_1} \gets D_{x_2+1,y_1}-1 -
D_{x_2+1,y_2+1} \gets D_{x_2+1,y_2+1}+1
即可。
代码实现如下:
#include<bits/stdc++.h>
#define N 1010
int n,m;
int map[N][N],d[N][N];
struct node {
int x1,y1,x2,y2;
};
node a[N];
namespace WalkerV {
void Read() {
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++) {
scanf("%d%d%d%d",&a[i].x1,&a[i].y1,&a[i].x2,&a[i].y2);
}
return;
}
void Solve() {
for(int i=1;i<=m;i++) {
d[a[i].x1][a[i].y1]++;
d[a[i].x2+1][a[i].y1]--;
d[a[i].x1][a[i].y2+1]--;
d[a[i].x2+1][a[i].y2+1]++;
}
for(int i=1;i<=n;i++) {
for(int j=1;j<=n;j++) {
map[i][j]=map[i][j-1]+map[i-1][j]-map[i-1][j-1]+d[i][j];
}
}
return;
}
void Print() {
for(int i=1;i<=n;i++) {
for(int j=1;j<=n;j++) {
printf("%d%c",map[i][j],j==n?'\n':' ');
}
}
return;
}
}
int main()
{
WalkerV::Read();
WalkerV::Solve();
WalkerV::Print();
return 0;
}