【题意】给了n个点,求一个正方形能围住的最大点数,同样正方形平行于坐标轴。
【解题方法1】线段树+扫描线。AC时间:30ms。
//
//Created by just_sort 2016/12/3
//Copyright (c) 2016 just_sort.All Rights Reserved
//
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/hash_policy.hpp>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
using namespace __gnu_pbds;
typedef long long LL;
typedef pair<int, LL> pp;
#define MP(x,y) make_pair(x,y)
const int maxn = 10010;
typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update>order_set;
//head
LL L, R, n, r;
LL b[3005];
struct seg{
LL x, y, v;
seg(){}
seg(LL x, LL y, LL v):x(x), y(y), v(v){}
}s[3005];
struct node{
int l, r;
LL num, lazy;
}T[30005];
bool cmp1(const seg &a, const seg &b)
{
if(a.x == b.x) return a.v > b.v;
return a.x < b.x;
}
bool cmp2(const seg &a, const seg &b)
{
return a.y < b.y;
}
void pushup(int rt)
{
T[rt].num = max(T[rt*2].num, T[rt*2+1].num);
}
void pushdown(int rt)
{
if(T[rt].lazy != 0)
{
T[rt*2].lazy += T[rt].lazy;
T[rt*2+1].lazy += T[rt].lazy;
T[rt*2].num += T[rt].lazy;
T[rt*2+1].num += T[rt].lazy;
T[rt].lazy = 0;
}
}
void Build(int l, int r, int rt)
{
T[rt].l = l, T[rt].r = r, T[rt].num = T[rt].lazy = 0;
if(l == r) return ;
int mid = (l + r) / 2;
Build(l, mid, rt*2);
Build(mid+1, r, rt*2+1);
}
void update(int v, int rt)
{
if(L <= T[rt].l && T[rt].r <= R){
T[rt].lazy += v;
T[rt].num += v;
return ;
}
pushdown(rt);
int mid = (T[rt].l + T[rt].r) / 2;
if(L <= mid) update(v, rt*2);
if(mid < R) update(v, rt*2+1);
pushup(rt);
}
int main()
{
while(scanf("%I64d%I64d",&n,&r)!=EOF)
{
memset(b, 0, sizeof(b));
for(int i = 1; i <= n; i++){
LL x, y;
scanf("%I64d%I64d",&x, &y);
s[3*i - 2] = seg(x, y, 1);
s[3*i - 1] = seg(x+r, y, -1);
s[3*i] = seg(x, y+r, 0);
}
sort(s+1, s+3*n+1, cmp2);
for(int i = 1; i <= 3*n; i++) b[i] = s[i].y;
int sz = unique(b+1, b+3*n+1) - b - 1;
sort(s+1, s+3*n+1, cmp1);
Build(1, sz, 1);
LL ans = 0;
for(int i = 1; i <= 3*n; i++){
if(s[i].v == 0) continue;
L = lower_bound(b + 1, b + sz + 1, s[i].y) - b;
R = lower_bound(b + 1, b + sz + 1, s[i].y + r) - b;
update(s[i].v, 1);
ans = max(ans, T[1].num);
}
printf("%lld\n", ans);
}
return 0;
}
【解题方法2】 双扫描线+暴力 AC时间:780ms
【具体步骤】首先将所有点按横坐标大小排序,然后以a[i].x为第一条竖扫描线,a[i].x+r为第二条竖扫描线,在存下在这个区间内的点的y坐标b[i]。将b数组从小到大排序,再以b[i]为第一条横扫描线,b[i]+r为第二条横扫描线,如果寻找到满足的坐标,curans++。最后找出最大的nexans,记得下一次操作curans前重新赋值!
【AC代码】
//
//Created by just_sort 2016/12/3
//Copyright (c) 2016 just_sort.All Rights Reserved
//
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/hash_policy.hpp>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
using namespace __gnu_pbds;
typedef long long LL;
typedef pair<int, LL> pp;
#define MP(x,y) make_pair(x,y)
const int maxn = 10010;
typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update>order_set;
//head
struct node{
int x, y;
node(){}
node(int x, int y) : x(x), y(y) {}
bool operator<(const node &rhs) const{
if(x == rhs.x) return y < rhs.y;
return x < rhs.x;
}
}a[1010];
int b[1010];
int main()
{
int n, r;
while(scanf("%d%d",&n,&r) != EOF)
{
for(int i = 1; i <= n; i++) scanf("%d%d",&a[i].x,&a[i].y);
sort(a+1, a+n+1);
int curans = 0, nexans = 0;
for(int i = 1; i <= n; i++){
int xUp = a[i].x + r;
int k = 0;
for(int j = i; j <= n; j++){
if(a[j].x <= xUp){
b[++k] = a[j].y;
}
}
sort(b+1, b+k+1);
for(int j = 1; j <= k; j++){
int yUp = b[j] + r;
curans = 0;
for(int l = j; l <= k; l++){
if(b[l] <= yUp){
curans++;
}
}
nexans = max(nexans, curans);
}
}
printf("%d\n",nexans);
}
return 0;
}