周赛D. Digging for Gold(扫描线)
给出二维平面上的一些点。
询问一个\(K\times K\)的正方形,最多能覆盖多少点。
做法:
考虑这个正方形的一个角。这个角确定了,正方形也就确定了。
对于一个点,合法的角的坐标范围形成了一个矩形。
问题转化为,求一些矩形的最大重合点是多少。
扫描线即可。
时间复杂度O(nlogn)。
//对一个点(x,y)来说
//一个矩形内的点是合法的
//那就二维差分
//
//对每个(x,y)对应一个矩形
//求这些矩形的最大覆盖点
//用扫描线
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
int n,m,k;
int t[maxn],mm;
struct {
pair<int,int> p[4];
//e表示矩形的长
}jx[maxn];
struct qnode {
int l,r,v;
};
vector<qnode> g[maxn];
int c[maxn<<2],lz[maxn<<2];
void pushdown (int i,int l,int r) {
int mid=(l+r)>>1;
if (lz[i]) {
c[i<<1]+=lz[i];
lz[i<<1]+=lz[i];
c[i<<1|1]+=lz[i];
lz[i<<1|1]+=lz[i];
lz[i]=0;
}
}
void up (int i,int l,int r,int L,int R,int v) {
if (l>=L&&r<=R) {
c[i]+=v;
lz[i]+=v;
return;
}
pushdown(i,l,r);
int mid=(l+r)>>1;
if (L<=mid) up(i<<1,l,mid,L,R,v);
if (R>mid) up(i<<1|1,mid+1,r,L,R,v);
c[i]=max(c[i<<1],c[i<<1|1]);
}
map<pair<int,int> ,int> mp;
int gg[200][200];
int main () {
scanf("%d%d%d",&n,&m,&k);
if (k==1) {
int ans=0;
while (m--) {
int x,y;
scanf("%d%d",&x,&y);
mp[{x,y}]++;
ans=max(ans,mp[{x,y}]);
}
printf("%d\n",ans);
return 0;
}
for (int i=1;i<=m;i++) {
int x,y;
scanf("%d%d",&x,&y);
jx[i].p[0]={x-k+1,y-k+1};
jx[i].p[1]={x,y-k+1};
jx[i].p[2]={x,y};
jx[i].p[3]={x-k+1,y};
for (int j=0;j<4;j++) {
//printf("%d: %d %d\n",i,jx[i].p[j].first,jx[i].p[j].second);
t[++mm]=jx[i].p[j].first;
t[++mm]=jx[i].p[j].second;
}
}
sort(t+1,t+mm+1);
mm=unique(t+1,t+mm+1)-t-1;
for (int i=1;i<=m;i++) {
for (int j=0;j<4;j++) {
jx[i].p[j].first=upper_bound(t+1,t+mm+1,jx[i].p[j].first)-t-1;
jx[i].p[j].second=upper_bound(t+1,t+mm+1,jx[i].p[j].second)-t-1;
}
// for (int j=jx[i].p[0].first;j<=jx[i].p[1].first;j++) {
// for (int kk=jx[i].p[0].second;kk<=jx[i].p[2].second;kk++) {
// gg[j][kk]++;
// }
// }
}
// for (int i=1;i<=mm;i++) {
// for (int j=1;j<=mm;j++) {
// printf("%d ",gg[i][j]);
// }
// puts("");
// }
// return 0;
for (int i=1;i<=m;i++) {
g[jx[i].p[0].first].push_back({jx[i].p[0].second,jx[i].p[3].second,1});
g[jx[i].p[1].first+1].push_back({jx[i].p[1].second,jx[i].p[2].second,-1});
}
int ans=0;
for (int i=1;i<=mm;i++) {
for (qnode it:g[i]) {
int l=it.l;
int r=it.r;
int v=it.v;
//printf("%d %d %d %d\n",i,l,r,v);
up(1,1,mm,l,r,v);
}
//printf("%d\n",c[1]);
ans=max(ans,c[1]);
}
printf("%d\n",ans);
}
/*
1000000000 4 1000000000
1000000000 1000000000
1000000000 1
1 1000000000
1 1
*/