@xiaoziyao
2021-07-09T20:03:03.000000Z
字数 1198
阅读 991
解题报告
网格中有个格子被涂黑,对于 ,求大小为 且能覆盖 个黑色格子的正方形数量。( ,值域范围 )
考虑答案的范围是很广的,显然不能枚举每个答案并检验其覆盖黑色格子数量。
正难则反,我们发现每个黑色格子 被覆盖当且仅当正方形的右下角在 范围内,也就是在一个以 为左上角,边长为 的正方形内。
问题被转化成对于 ,求有多少个整点被 个矩形覆盖,这是经典问题,扫描线的同时暴力统计一下就好了,复杂度 。
扫描线注意细节。
#include<stdio.h>
#include<algorithm>
#include<map>
using namespace std;
const int maxn=100005;
int n,k,tot;
int cnt[maxn<<1],num[maxn<<1],val[maxn<<1];
long long ans[maxn];
map<int,int>mp;
struct line{
int x,ya,yb,opt;
}l[maxn<<1];
inline int cmp(line a,line b){
return a.x<b.x;
}
int main(){
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++){
int a,b;
scanf("%d%d",&a,&b);
l[2*i-1]=line{a,b,b+k-1,1},l[2*i]=line{a+k,b,b+k-1,-1};
num[2*i-1]=b,num[2*i]=b+k;
}
sort(num+1,num+1+2*n),sort(l+1,l+1+2*n,cmp);
for(int i=1;i<=2*n;i++)
if(i==1||num[i]!=num[i-1])
mp[num[i]]=++tot,val[tot]=num[i];
for(int i=1;i<=2*n;i++){
int ya=mp[l[i].ya],yb=mp[l[i].yb+1],opt=l[i].opt,len=l[2*n].x-l[i].x;
for(int j=ya;j<yb;j++){
ans[cnt[j]]-=1ll*len*(val[j+1]-val[j]);
cnt[j]+=opt;
ans[cnt[j]]+=1ll*len*(val[j+1]-val[j]);
}
}
for(int i=1;i<=n;i++)
printf("%lld%c",ans[i],i==n? '\n':' ');
return 0;
}