考虑一个矩形可覆盖一个点的矩形的右上角的位置,我们发现是一个矩形。那么被矩形覆盖次数最多的点就是矩形的右上角。
问题转化为被矩形覆盖次数最多的矩形被覆盖了多少次。
#include
#define lc l,mid,x<<1
#define rc mid+1,r,x<<1|1
using namespace std;
typedef long long LL;
typedef int lint;
const lint dt = 2000010;
void trans( lint& x,lint& y ){
lint xx = x,yy = y;
x = xx-yy+dt; y = xx+yy+dt;
}
struct Point{
lint x,y,c;
Point( lint xx = 0,lint yy = 0,lint cc = 0 ){
x = xx;y = yy;c=cc;
}
bool operator <( const Point& b )const{
if( y == b.y ){
if( x == b.x ) return c < b.c;
return x < b.x;
}
return y < b.y;
}
};
vector ve;
lint tree[16*dt],laz[16*dt];
void push_down( lint x ){
if( laz[x] ){
tree[x<<1] += laz[x];
tree[x<<1|1]+=laz[x];
laz[x<<1]+= laz[x];
laz[x<<1|1]+=laz[x];
laz[x]=0;
}
return;
}
void push_up( lint x ){
tree[x] = max(tree[x<<1] , tree[x<<1|1]);
}
void update( lint ll,lint rr,lint v,lint l,lint r,lint x ){
if( ll <= l && rr >= r ){
tree[x] += v;
laz[x] += v;
return;
}
push_down(x);
lint mid = l + r>>1;
if( ll <= mid ) update( ll,rr,v,lc );
if( rr > mid ) update( ll,rr,v,rc );
push_up(x);
}
lint query( lint ll,lint rr,lint l,lint r,lint x ){
if( ll <= l && rr >= r ){
return tree[x] ;
}
push_down(x);
lint mid = l+r>>1;
lint res = 0;
if(ll<= mid) res = max(res, query( ll,rr,lc ));
if(rr>mid) res = max(res,query(ll,rr,rc));
push_up(x);
return res;
}
int main(){
lint n,r,ans = 0;
scanf("%d%d",&n,&r);
for( lint x,y,i = 1;i <= n;i++ ){
scanf("%d%d",&x,&y);
trans(x,y);
ve.push_back( Point( x,y,0 ) );ve.push_back( Point( x+2*r,y+2*r,1 ) );
}
sort( ve.begin(),ve.end() );
for( lint i= 0 ;i< ve.size();i++ ){
Point cur= ve[i];
if( cur.c == 0 ){
update( cur.x,cur.x+2*r,1,0,4*dt,1 );
lint res = query( 0,4*dt,0,4*dt,1 );
ans = max( ans,res );
}else{
lint res = query( 0,4*dt,0,4*dt,1 );
ans = max( ans,res );
update( cur.x-2*r ,cur.x,-1,0,4*dt,1 );
}
}
printf("%d",ans);
return 0;
}