题意:平面上有n个点,选一个W×H的矩形,使得矩形内的点最多。
思路:简单的扫描线+线段树,但是调了好久,时间长不写就sb了,哎。。。。线段树中的节点表示以这个节点开始,长度为W的区间内的点的个数。y从小到大扫过去就行了。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<set>
#include<cmath>
#include<vector>
#include<bitset>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define eps 1e-6
#define pi acos(-1.0)
using namespace std;
typedef long long ll;
const int maxn = 100000 + 10;
struct Point
{
int x,y,z;
Point(int x = 0,int y = 0,int z = 0):x(x),y(y),z(z){}
bool operator < (const Point & a) const
{
if(y == a.y) return x < a.x;
return y < a.y;
}
}pt[maxn],S[maxn];
int maxv[maxn<<2],addv[maxn<<2];
bool cmp(Point a,Point b)
{
return a.x < b.x;
}
inline void PushUp(int rt)
{
maxv[rt] = max(maxv[rt<<1],maxv[rt<<1|1]);
}
void PushDown(int rt)
{
if(addv[rt])
{
addv[rt<<1] += addv[rt];
addv[rt<<1|1] += addv[rt];
maxv[rt<<1] += addv[rt];
maxv[rt<<1|1] += addv[rt];
addv[rt] = 0;
}
}
void build(int l,int r,int rt)
{
maxv[rt] = addv[rt] = 0;
if(l == r) return ;
int m = (l + r)>>1;
build(l,m,rt<<1);
build(m + 1,r,rt<<1|1);
}
void Update(int L,int R,int l,int r,int rt,int v)
{
if(l >= L && r <= R)
{
addv[rt] += v;
maxv[rt] += v;
return ;
}
PushDown(rt);
int m = (l + r)>>1;
if(m >= L) Update(L,R,l,m,rt<<1,v);
if(m < R) Update(L,R,m + 1,r,rt<<1|1,v);
PushUp(rt);
}
int main()
{
// freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int n,W,H;
while(~scanf("%d",&n))
{
if(n < 0) break;
scanf("%d%d",&W,&H);
int x,y,N = 0;
for(int i = 0;i < n;++i)
{
scanf("%d%d",&x,&y);
pt[i].x = x + 20001;
pt[i].y = y + 20001;
N = max(N,pt[i].x);
}
build(1,N,1);
sort(pt,pt + n);
for(int i = 0;i < n;++i)
{
S[i].z = pt[i].y;
S[i].x = pt[i].x - W;
S[i].y = pt[i].x;
S[i].x = max(S[i].x,1);
S[i].y = min(S[i].y,N);
}
int ans = 0,last = 0;
for(int i = 0;i < n;++i)
{
Update(S[i].x,S[i].y,1,N,1,1);
while(last <= i && S[i].z - S[last].z > H)
Update(S[last].x,S[last].y,1,N,1,-1),last++;
ans = max(ans,maxv[1]);
}
printf("%d\n",ans);
}
return 0;
}