传送门
思路:
扫描线的经典问题
然而并不是很会做……
对x坐标差分一下(例如(x,y)类型为1,(x+w,y)的类型就是-1,以便于之后扫描可以去除该点),然后对y坐标转化为正数(便于操作为线段树上的区间,因为这里坐标值都很小所以不用离散化,加上一个较大值就可以了)
每次加1的点(-1点就是消去原先的1点了)时实际上是区间覆盖操作,表示该点与矩形的相对位置,然后查一下最大值就行了
总的来说就是差分加点+扫描线+线段树的区间覆盖,单点查max
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define M 10005
using namespace std;
int n,X,Y;
int tr[M<<3],lazy[M<<3];
struct node{
int x,y,tp;
}a[M<<1];
int in()
{
int t=0;char ch=getchar();bool f=0;
while (ch>'9'||ch<'0') f=(ch=='-'),ch=getchar();
while (ch>='0'&&ch<='9') t=(t<<1)+(t<<3)+ch-48,ch=getchar();
return f?-t:t;
}
bool cmp(node a,node b){return a.x<b.x;}
void pushdown(int rt)
{
if (!lazy[rt]) return;
lazy[rt<<1]+=lazy[rt];
lazy[rt<<1|1]+=lazy[rt];
tr[rt<<1]+=lazy[rt];
tr[rt<<1|1]+=lazy[rt];
lazy[rt]=0;
}
void update(int rt,int begin,int end,node now)
{
if (now.y<=begin&&end<=now.y+Y)
{
lazy[rt]+=now.tp;
tr[rt]+=now.tp;
return;
}
pushdown(rt);
int mid=begin+end>>1;
if (mid>=now.y) update(rt<<1,begin,mid,now);
if (mid<now.y+Y) update(rt<<1|1,mid+1,end,now);
tr[rt]=max(tr[rt<<1],tr[rt<<1|1]);
}
void work()
{
X=in();Y=in();
int S=1<<30,T=-1<<30;
for (int i=1;i<=n;++i)
a[i*2-1]=(node){in(),in()+20000,1},
a[i*2]=(node){a[i*2-1].x+X+1,a[i*2-1].y,-1},
S=min(a[i<<1].y,S),T=max(a[i<<1].y,T);
sort(a+1,a+n*2+1,cmp);
int ans=0;
for (int i=1;i<=n<<1;++i)
update(1,S,T,a[i]),
ans=max(ans,tr[1]);
printf("%d\n",ans);
}
main()
{
for (n=in();n>0;n=in()) work();
}