#1421: Four fork tree time limit: 20000ms single point limit: 2000ms memory limit: 256MB description
Little ho: Next weekend we're going to play in the next city.
Small hi: Anyway, very close to the back, good ah.
Little ho: Well, let me start by planning the route.
Little Ho opened the map app in the phone and moved the coordinates to the city next door. A variety of shops are displayed on the street map.
Little hi: Little ho, do you know how the map app calculates the shops around you?
Little ho: Hey. Didn't think about it.
Little hi: Actually this is also a very interesting question. Let's first simplify the model, assuming there is a plan with n points distributed above, and the coordinates of the point I are (X[i],y[i]).
Little ho: Use points to represent shops.
Little hi: Yes, and if we are in the coordinates of (a A, A, b), then we have a radius of R in the range (including the edge), how many points?
Little ho: It feels like a very interesting question, let me think about it.
Tip: Four fork tree (quadtree) input
Line 1th: 2 integer n,m. 1≤n≤50,000,0≤m≤5,000.
2nd.. N+1 line: 2 integers per line x, Y, line i+1 represents the coordinates of the point I, guaranteed no duplicate points. 0≤x,y≤30,000
Line n+2..n+m+1:3 integer a,b,r per line, indicating the center coordinate (a, b) of the query, and radius R. 0≤a,b,r≤30,000 Output
1th.. M-line: 1 integers per line, and line I indicates the number of points in the center of the (x, y) query. Sample input
2 2
1 1
2 2
2 2 1
2 2 2
Sample output
1
2
tip: Four fork tree (quadtree)
Little ho: The simple idea is that I use a two-dimensional array to represent the entire floor plan. Assuming the range of coordinates is L, a l*l array is required.
For (A, B) and R, I check the b-r column to the B+r column of the a-r to the A+r row to see if there is a bit, and the point to (A, b) is less than or equal to R.
For L more than 10000 of the situation there is no way to achieve.
Little hi: Yes, in the case of large coordinate ranges and points, there is a real problem.
Little ho: I was wondering if I could divide the whole area into small areas, each time in a small area nearby to find the nearest point.
Little hi: Little ho You have a great idea, and we might as well try it.
Little ho: How should that be divided?
Little hi: Do you remember the line tree? In the processing of the segment tree, we divide an interval from one point into two segments. Here we also use the same method to divide a region into 4 pieces:
From top to bottom, from left to right, labeled 1234 respectively.
We put all the points into these areas, in order to make an area in the number of points not too much, we set an area of the number of points limit.
If there are too many points in an area, we will take this area four points and put the new point in the sub-region.
Little ho: Sounds like a lot of sense.
Little hi: Of course it makes sense that this data structure is called "Quadtree (Quadtree)". Each of its basic units is:
Quadtreenode:
const node_capacity;//Each node contains a limit of the number of points, a constant
boundary;//The range of the node, which contains 4 parameters, the upper and lower left and right border of the region
points; A list of nodes within the region
Childnode;//contains 4 parameters representing 4 sub-regions
Assuming Node_capacity=1, then we can divide the entire region into:
Little ho: Well, I understand that, because it is similar to a line tree, then there is the same insert and query operation.
Little hi: Yes.
Quadtree insert operation: When inserting a new node (x, y), if it is not in the current region, exit, otherwise add it to the node list of the zone points, if the node list for the current region is full. Then the area is four points, and the node is added to the sub-region.
Insert (Quadtreenode Nownode, point P):
if (p not in nownode.boundary) then
Return
End if
if ( NowNode.points.length < node_capacity)
then NowNode.points.append (p)
Else
nownode.divide ()//area four min. For each
Childnode of Nownode
inserts (Childnode, p)
end for
end If
A quad-tree query operation is typically a range of points, so the parameters that are brought in are also an area range:
Query (Quadtreenode nownode, Range):
If (Quadtreenode.boundary does not intersect range) then
//The region of the node does not intersect the query area C2/>return empty
End if for each
p in nownode.points
if (p in range) and then
Pointsinrange.append (p)
End
for the If
(nownode.isdivide)
then//If the zone has been partitioned, then the nodes in the sub-zone may also be in
the for each childnode of Nownode
Query (childnode, range)
end for
end If
Return Pointsinrange
In our question, we can use a circle of external squares as an area to find a list of points, and then check whether it is within the circle.
Little ho: So it does look like the search is less quantitative.
Little hi: Yes, and the process of dynamically building a four-fork tree reduces the overhead of space.
Little ho: Well, let me try it out for a second.
Embarrassed-.-at the insertion point, fascinated, fascinated---whining-.-
Code:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std;
int xx[60000],yy[60000];
struct node{bool Fafe;
int length,hao[5],x[2],y[2];
node * clidren[4];
}PP[1000000];
void Lon (node *x) {x->length=0;
x->fafe=false;
} int a,b,r,ans,lp,ll; void pan (int i)//determine if in circle {if ((A-xx[i]) * (A-xx[i]) + (B-yy[i]) * (B-yy[i]) <=r*r) ans++; void Add (int ii,node
* x);
void Fen (node * x) {int mx= (x->x[0]+x->x[1]) >>1;
int my= (x->y[0]+x->y[1]) >>1; for (int i=0;i<4;i++) x->clidren[i]=&pp[lp++];//is divided into four x->clidren[0]->x[0]=x->x[0];x->clid
ren[0]->x[1]=mx;
x->clidren[0]->y[0]=x->y[0];x->clidren[0]->y[1]=my;
x->clidren[1]->x[0]=mx+1;x->clidren[1]->x[1]=x->x[1];
x->clidren[1]->y[0]=x->y[0];x->clidren[1]->y[1]=my;
x->clidren[2]->x[0]=x->x[0];x->clidren[2]->x[1]=mx; x->clidren[2]->y[0]=my+1;x->clidren[2]->y[1]=x->y[1];
x->clidren[3]->x[0]=mx+1;x->clidren[3]->x[1]=x->x[1];
x->clidren[3]->y[0]=my+1;x->clidren[3]->y[1]=x->y[1];
Yes for (int i=0;i<4;i++) lon (X->clidren[i]);
Yes for (int j=0;j< x->length; j + +) {int ii=x->hao[j]; for (int i=0;i<4;i++) {if (x->clidren[i]->x[0]<=xx[ii]&&x->clidren[i]->x[1]
>=xx[ii]&&x->clidren[i]->y[0]<=yy[ii]&&x->clidren[i]->y[1]>=yy[ii]) {
Add (Ii,x->clidren[i]);
Break
}}}//Yes x->fafe=true;
x->length=0;
yes} void Add (int ii,node * x)//insertion point {if (!x->fafe) {x->hao[x->length++]=ii;
if (x->length>ll) {fen (x); }} else {for (int i=0;i<4;i++) {if (x->clidren[i]->x[0]<=xx[ii]&&x->clidren[i]->x[1]>=xx[ii]&&x->clidren[i]-
>Y[0]<=YY[II]&&X->CLIDREN[I]->Y[1]>=YY[II]) {Add (Ii,x->clidren[i]);
/*x->clidren[i]->hao[x->clidren[i]->length++]=ii;--was wrong at first---this area may have been divided-.-
if (x->clidren[i]->length>ll) {fen (x->clidren[i]);
}*/break; }}}} void query (node * x,int l,int r,int xi,int s)//Find {if (!x->fafe) {if (x->lengt
h) {for (int i=0;i<x->length;i++) pan (X->hao[i]);
} return; } for (int i=0;i<4;i++) {if (l>=x->clidren[i]->x[0]&&r<=x->clidren[i]->x[1]& AMP;&XI>=X->CLIDREN[I]->Y[0]&&S<=X->CLIDREN[I]->Y[1]) {query (x->clid REn[i],l,r,xi,s);
return;
}} if (L>=x->clidren[1]->x[0]) {query (x->clidren[1],l,r,xi,x->clidren[1]->y[1]);
Query (x->clidren[3],l,r,x->clidren[3]->y[0],s);
} else if (R<=x->clidren[0]->x[1]) {query (x->clidren[0],l,r,xi,x->clidren[0]->y[1]);
Query (x->clidren[2],l,r,x->clidren[2]->y[0],s);
} else if (Xi>=x->clidren[2]->y[0]) {query (x->clidren[2],l,x->clidren[2]->x[1],xi,s);
Query (x->clidren[3],x->clidren[3]->x[0],r,xi,s);
} else if (S<=x->clidren[0]->y[1]) {query (x->clidren[0],l,x->clidren[0]->x[1],xi,s);
Query (x->clidren[1],x->clidren[1]->x[0],r,xi,s);
} else {query (x->clidren[0],l,x->clidren[0]->x[1],xi,x->clidren[0]->y[1]); Query (X->clidren[1],x->clidren[1]->x[0],r,xi,x->clidren[1]->y[1]);
Query (x->clidren[2],l,x->clidren[2]->x[1],x->clidren[2]->y[0],s);
Query (x->clidren[3],x->clidren[3]->x[0],r,x->clidren[3]->y[0],s);
}} int main () {int n,m;
scanf ("%d%d", &n,&m);
pp[0].x[0]=0;pp[0].x[1]=30000;
pp[0].y[0]=0;pp[0].y[1]=30000;
Lon (&pp[0]); lp=1;
ll=4;
for (int i=0;i<n;i++) {scanf ("%d%d", &xx[i],&yy[i]);
Add (i,&pp[0]);
} for (int i=0;i<m;i++) {scanf ("%d%d%d", &a,&b,&r);
ans=0;
Query (&pp[0],max (0,a-r), Min (30000,a+r), Max (0,b-r), Min (30000,b+r));
printf ("%d\n", ans);
} return 0;
}/* 2 3 0 1 */