Test instructions
This day, Sjy seems bored. at home.
On a chessboard, there are n black pieces. Every time he put a black pawn on the board. Either put on a white piece, assuming it is a white piece, he will find out the recent black pieces from this white piece.
The distance here is Manhattan distance (|x1-x2|+|y1-y2|).
Now give the n<=500000 an initial piece. and m<=500000 operations. For each white piece, the distance from the short black piece of the white piece is output. There may be multiple pieces in the same lattice.
Idea: Kdtree first question.
What is a kdtree?
Now, for example, there are some points on the two-dimensional plane that we first divide by dimension:
For example, for the first time, divide the X dimension. So we'll find the point where the x-coordinate is the median in all points, and it's taken as the root. Points with an x-coordinate that is less than the median are divided into the left subtree. Otherwise, divide to the right sub-tree. Then the points of the remaining two sides are divided recursively. The next division is based on the Y dimension. Again the next division is based on the X dimension. And so on
The information stored for each node includes the coordinates of the upper-left and lower-right corners of the rectangle for all points of the subtree at the root of the point. We can update it at the end of the division.
So how do we query for a given coordinate (x, y) Manhattan distance near the nearest point?
Record global variable ans, which represents the minimum distance for the moment.
The initial value is set to INF.
Starting from the root node, recursive down query: first with the current node to update the answer, and then see the corresponding rectangle of the left and right subtree, if the inquiry point in the rectangle outside the rectangular distance of the inquiry point to the nearest distance of the rectangle. Otherwise, it is 0.
We prefer the one side of the rectangle with a smaller distance to be recursive downwards.
After asking. If there is one side of the rectangular distance is not greater than the current optimal solution, then ask another side.
According to God Ben, this process is the worst O (sqrt (n)).
Consider inserting.
Maintain the current division of the basis of which dimension.
From the root start recursively down.
First update the current node with the insertion point, and then infer whether the Zuozi or right subtree should be inserted into the current node, and if the inserted part is empty, insert it directly. Otherwise, it is recursively inserted.
So there's one last question. That is, the subject of Kdtree must be implemented with pointers. Otherwise, the movement in the large array is unusually slow, and queries and changes are made to tle.
Code: (pointer version)
#include <cstdio> #include <cstring> #include <climits> #include <iostream> #include < Algorithm>using namespace Std; #define Min (A, B) ((a) < (b)? (a):(B)) #define MAX (A, B) ((a) > (b)? ( A):(B)) #define ABS (x) ((x) >0? ( x):-(x)) #define N 500010#define m 500010int N, M; struct point {int x, y; Point (int _x = 0, int _y = 0): X (_x), Y (_y) {} void Set (int _, int __) {x = _, y = __; }}p[n + m];int Dis (const point &a, const point &b) {return abs (a.x-b.x) + ABS (A.Y-B.Y);} bool Sign;inline BOOL CMP (const point &a, const point &b) {if sign return a.x < b.x | | (a.x = = b.x && a.y < B.Y); else return A.Y < B.Y | | (A.y = = B.y && a.x < b.x);} struct Node {node *l, *r; int x[2], y[2]; Point P; void Setp (const point &p) {p = p; X[0] = x[1] = p.x; Y[0] = y[1] = p.y; } int Dis (const point &p) const {int res = 0; if (p.x < x[0] | | p.x > X[1]) Res + = (p.x < x[0])?
X[0]-p.x:p.x-x[1]; if (P.y < y[0] | | p.y > Y[1]) Res + = (P.y < y[0])? Y[0]-p.y:p.y-y[1]; return res; } void Up (Node *b) {x[0] = Min (x[0], b->x[0]); X[1] = Max (x[1], b->x[1]); Y[0] = Min (y[0], b->y[0]); Y[1] = Max (y[1], b->y[1]); }}mem[n + M], *c = Mem, tnull, *null = &Tnull; Node *build (int tl, int tr, bool d) {if (tl > TR) return null; int mid = (tl + tr) >> 1; sign = D; Std::nth_element (p + TL + 1, p + mid + 1, p + TR + 1, CMP); Node *q = c + +; Q->SETP (P[mid]); Q->l = Build (TL, mid-1, D ^ 1); Q->r = Build (mid + 1, tr, d ^ 1); if (q->l! = null) q->up (Q->L); if (q->r! = null) q->up (Q->R); return q;} #define INF 0x3f3f3f3fint res;void Ask (Node *q, const point &p) {res = Min (res, Dis (Q->p, p)); int DisL = q->l! = null? Q->l->dis (P): INF; int DisR = q->r! =Null? Q->r->dis (P): INF; if (DisL < DisR) {if (q->l! = null) Ask (Q->L, p); if (DisR < res && Q->r! = null) Ask (Q->r, p); } else {if (q->r! = null) Ask (Q->r, p); if (DisL < res && q->l! = null) Ask (Q->L, p); }} void Insert (node *root, const point &p) {node *q = c + +; Q->l = Q->r = null; Q->SETP (P); sign = 0; while (1) {root->up (q); if (CMP (q->p, root->p)) {if (root->l = = null) {root->l = q; Break } Else root = root->l; } else {if (root->r = = null) {root->r = q; Break } Else root = root->r; } sign ^= 1; }} int main () {#ifndef Online_judge freopen ("tt.in", "R", stdin); Freopen("Tt.out", "w", stdout); #endif scanf ("%d%d", &n, &m); register int i; int ope, x, y; for (i = 1; I <= n; ++i) {scanf ("%d%d", &x, &y); P[i] = point (x, y); } node* root = Build (1, n, 0); while (m--) {scanf ("%d%d%d", &ope, &x, &y); if (ope = = 1) Insert (root, point (x, y)); else {res = INF; Ask (Root, point (x, y)); printf ("%d\n", res); }} return 0;}
BZOJ2648 sjy Pendulum Pawn