题目大意:
小明对着墙壁画矩形,问小明画的矩形里面重叠k次的区域面积是多大。
解题思路:
首先,我们可以想到对画的一片区域进行+1操作,最后扫描一遍画的区域,若某个点的和为k我们就记录下来。
首先,我们可以试一下naive的+1,发现复杂多太高。这时候引入一个新结构叫做二维差分,二维差分再配合二维前缀和就可以达到O(n^2)的更新一片区域。关于二维差分,这里有一个解释:
https://www.cnblogs.com/LMCC1108/p/10753451.html
二维差分的公式是:假若我们想对(x1,y1)到(x2,y2)的区域进行+val操作。我们可以:
其中gra是棋盘。为什么可以这样呢?简要来说,就是通过引入+val 和-val的标签后,在计算二位前缀和时可以达到只对某个区域+val的操作。大家可以试着动手算算。二维前缀和的公式是:
但注意在边界时,有些数组越界的项我们是需要去掉的。
AC代码:
#include <bits/stdc++.h>
using namespace std;
const int MAXN=1e3+10;
int main(){
int n,k;cin>>n>>k;
vector<vector<int>> chess(MAXN,vector<int>(MAXN,0));
for(int i=0;i<n;i++){
int x1,y1,x2,y2;cin>>x1>>y1>>x2>>y2;
x2-=1;y2-=1;
chess[x1][y1]+=1;
chess[x1][y2+1]-=1;
chess[x2+1][y1]-=1;
chess[x2+1][y2+1]+=1;
}
int ans=0;
for(int x=0;x<MAXN;x++)
for(int y=0;y<MAXN;y++){
int ret=chess[x][y];
if(x>=1)ret+=chess[x-1][y];
if(y>=1)ret+=chess[x][y-1];
if(x>=1 && y>=1)ret-=chess[x-1][y-1];
chess[x][y]=ret;
if(ret==k)ans++;
}
cout<<ans<<endl;
return 0;
}