使用线段树,将(1,1+r,1+2r),(2,2+r,2+2r),(3,3+r,3+2r)以此类推,每个看成一个节点,对y进行建树,然后枚举x,维护最大值即可。
代码如下:
#include<cstdio>
#include<algorithm>
#include<string>
#include<vector>
using namespace std;
const int maxn=5e5+9;
vector<int>x[maxn];
vector<int>y[maxn];
int num_x[maxn];
int num_y[maxn];
int n,rr;
struct node{
int l,r,maxn,lazy;
}t[5*maxn];
void pushup(int cur)
{
t[cur].maxn=max(t[cur<<1].maxn,t[cur<<1|1].maxn);
}
void pushdown(int cur)
{
if(t[cur].lazy)
{
t[cur<<1].maxn+=t[cur].lazy;
t[cur<<1].lazy+=t[cur].lazy;
t[cur<<1|1].maxn+=t[cur].lazy;
t[cur<<1|1].lazy+=t[cur].lazy;
t[cur].lazy=0;
}
}
void build(int l,int r,int cur)
{
t[cur].l=l;
t[cur].r=r;
t[cur].maxn=0;
t[cur].lazy=0;
if(l==r)
{
t[cur].maxn=num_y[l]+num_y[l+rr]+num_y[l+2*rr];
return;
}
int m=(l+r)>>1;
build(l,m,cur<<1);
build(m+1,r,cur<<1|1);
pushup(cur);
}
void update_point(int l,int r,int now,int cur,int num)
{
if(l==r)
{
t[cur].maxn+=num;
t[cur].lazy+=num;
return;
}
pushdown(cur);
int m=(l+r)>>1;
if(now<=m)
update_point(l,m,now,2*cur,num);
else
update_point(m+1,r,now,2*cur+1,num);
pushup(cur);
}
int main()
{
scanf("%d%d",&n,&rr);
for(int i=1;i<=n;i++)
{
int xx,yy;
scanf("%d%d",&xx,&yy);
xx++,yy++;
x[xx].push_back(yy);
y[yy].push_back(xx);
num_x[xx]++;
num_y[yy]++;
}
build(1,100001,1);
int ans=0;
for(int i=1;i<=100001;i++)
{
int fuck=0;
for(int j=i;fuck!=3;j+=rr)
{
for(int k=0;k<x[j].size();k++)
{
if(x[j][k]-rr>0)
update_point(1,100001,x[j][k]-rr,1,-1);
if(x[j][k]-2*rr>0)
update_point(1,100001,x[j][k]-2*rr,1,-1);
update_point(1,100001,x[j][k],1,-1);
}
fuck++;
}
fuck=0;
ans=max(ans,num_x[i]+num_x[i+rr]+num_x[i+2*rr]+t[1].maxn);
for(int j=i;fuck!=3;j+=rr)
{
for(int k=0;k<x[j].size();k++)
{
if(x[j][k]-rr>0)
update_point(1,100001,x[j][k]-rr,1,1);
if(x[j][k]-2*rr>0)
update_point(1,100001,x[j][k]-2*rr,1,1);
update_point(1,100001,x[j][k],1,1);
}
fuck++;
}
}
printf("%d\n",ans);
return 0;
}