题意:给你s个信号源的坐标,所有信号源的有效半径都为r,有w条线段,信号穿过线段有效半径会减一
然后有p个询问,每次给你一个点,问该点能接收到哪些信号源的信号
由于半径很小,而且传感器之间的距离不小于r,对于每次询问,直接枚举到该点距离小于r的传感器即可
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const double eps = 1e-6;
struct P
{
int x, y;
P(){}
P(int _x, int _y){x = _x; y = _y;}
};
bool operator < (P a, P b) {return (a.x != b.x) ? a.x < b.x : a.y < b.y;}
P operator - (P a, P b) {return P(a.x - b.x, a.y - b.y);}
int cross(P a, P b) {return a.x * b.y - b.x * a.y;}
double dis(P a, P b) {return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y));}
// > 0 is clockwise
int direction(P p1, P p2, P p3) {return cross(p3 - p1, p2 - p1);}
// judge point np is on the segment p1-p2 or not
bool on_segment(P p1, P p2, P np)
{
if(np.x < min(p1.x, p2.x)) return false;
if(np.x > max(p1.x, p2.x)) return false;
if(np.y < min(p1.y, p2.y)) return false;
if(np.y > max(p1.y, p2.y)) return false;
return true;
}
// judge p1-p2 and p3-p4 is intersect or not
bool segment_intersect(P p1, P p2, P p3, P p4)
{
// 必须用 long long
ll d1 = direction(p1, p2, p3);
ll d2 = direction(p1, p2, p4);
ll d3 = direction(p3, p4, p1);
ll d4 = direction(p3, p4, p2);
if(d1 * d2 < 0 && d3 * d4 < 0) return true;
if(d1 == 0 && on_segment(p1, p2, p3)) return true;
if(d2 == 0 && on_segment(p1, p2, p4)) return true;
if(d3 == 0 && on_segment(p3, p4, p1)) return true;
if(d4 == 0 && on_segment(p3, p4, p2)) return true;
return false;
}
set<int> S[20005];
set<int>::iterator it;
P p_l[15], p_r[15];
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
for(int i = 0; i < 20005; i++)
S[i].clear();
int s, r, w, p;
scanf("%d%d%d%d", &s, &r, &w, &p);
for(int i = 0; i < s; i++)
{
int x, y;
scanf("%d%d", &x, &y);
S[x + 10000].insert(y);
}
for(int i = 0; i < w; i++)
scanf("%d%d%d%d", &p_l[i].x, &p_l[i].y, &p_r[i].x, &p_r[i].y);
while(p--)
{
P p1;
scanf("%d%d", &p1.x, &p1.y);
vector<P> ans;
for(int i = -r; i <= r; i++)
{
int x = p1.x + i, y = ceil(p1.y - sqrt(r*r - (p1.x - x)*(p1.x - x)));
int k = x + 10000;
if(k < 0 || k > 20000) continue;
it = S[k].lower_bound(y);
while(it != S[k].end())
{
P p2(x, *it++);
double d = dis(p1, p2);
if(d > r + eps) break;
double add = 0;
for(int k = 0; k < w; k++)
if(segment_intersect(p1, p2, p_l[k], p_r[k])) add++;
if(d + add < r + eps) ans.push_back(p2);
}
}
sort(ans.begin(), ans.end());
printf("%d ", ans.size());
for(int i = 0; i < ans.size(); i++)
printf("(%d,%d) ", ans[i].x, ans[i].y);
printf("\n");
}
}
return 0;
}