做法,
将读入的每个点(x,y)看做一个以该点为左上角宽W高H的矩形, 然后将矩形看做两条平行y轴(起点y-h,终点y)线,横坐标分别为 x , x+W;
然后可用经典的扫描线算法求解该题,即找出所有矩形重叠的最多次数,即所求值
证明 :
都在一个矩形内的点必定他们的上述规定的矩形都两两相交,而矩形两两相交必然有共同的交点是的所有矩形都相交于此;
#include <cstdio> #include <cstring> #include <iostream> #include <vector> #include <algorithm> #include <cctype> #include <set> using namespace std; #define lson l,m,(rt<<1) #define rson m+1,r,(rt<<1|1) const int N = 81500; const int maxn = 10010; const int yadd = 61000; int x[maxn],y[maxn],n,W,H; struct segment{ int x,y1,y2,flag; segment(int x,int y1,int y2,int f):x(x),y1(y1),y2(y2),flag(f){} bool operator < (const segment& rhs) const { return x < rhs.x || x == rhs.x && flag > rhs.flag; } }; vector<segment> ans; int MAX[N<<2],col[N<<2]; void build(int l,int r,int rt){ MAX[rt]=col[rt]=0; if(l==r) return; int m=(l+r)>>1; build(lson); build(rson); } void pushup(int rt){ MAX[rt]=max(MAX[rt<<1],MAX[rt<<1|1]); } void pushdown(int rt){ if(col[rt]!=0){ col[rt<<1]+=col[rt]; col[rt<<1|1]+=col[rt]; MAX[rt<<1]+=col[rt]; MAX[rt<<1|1]+=col[rt]; col[rt]=0; } } int Ans,ql,qr,fff; void update(int l,int r,int rt){ if(ql<=l&&r<=qr){ MAX[rt]+=fff; col[rt]+=fff; Ans= max(MAX[rt],Ans); return ; } pushdown(rt); int m=(l+r)>>1; if(ql<=m) update(lson); if(qr> m) update(rson); pushup(rt); } int MAXS = 81250; int main() { while(scanf("%d",&n)==1 && n!=-1){ scanf("%d %d",&W,&H); int xx,yy; ans.clear(); for(int i=1;i<=n;i++){ scanf("%d %d",&xx,&yy); x[i]=xx; y[i]=yy+yadd; ans.push_back(segment(x[i],y[i],y[i]-H,1)); ans.push_back(segment(x[i]+W,y[i],y[i]-H,-1)); } sort(ans.begin(),ans.end()); build(1,MAXS,1); int res=0; for(int i=0;i<ans.size();i++){ segment& temp = ans[i]; Ans=0; ql=temp.y2,qr=temp.y1; fff=temp.flag; update(1,MAXS,1); res=max(res,Ans); } printf("%d\n",res); } return 0; }