After a few days of research kd-tree, I can say Kd-tree is to follow the basic ideas casually write on it.
Taking the two-dimensional plane as an example, there are several points on the two-dimensional plane, how do we establish kd-tree?
The first layer divides all the points into two parts in the median of x coordinates, and puts them on the left and right subtree, the second layer in the y-coordinate for the median and then the current set equally, and the third layer is still in the x-coordinate ... So recursively go on.
As an example of querying the nearest point, we find that the query point on the current node should be divided into which subtree. The advantage of traversing this subtree, if the best answer found in this subtree is less than the distance from this point to the dividing line, there is no need to traverse another subtree, which is said to be expected to be O (n^ (D-1)/d), But I don't know why
Three examples inscribed with three different styles of code ...
1, hdu4347
Find the M point nearest to a point in the K-dimensional space, defined as the Euclidean distance.
Kd-tree the basic questions, casually write on it ....
#include <queue> #include <cstdio> #include <vector> #include <cstring> #include <algorithm&
Gt
using namespace Std;
const int MAXN = 100005;
int n,k,q,m,d,i,root;
int son[maxn][2];
struct point {int x[5];
void Read () {for (int i=0;i<k;i++) scanf ("%d", &x[i]);
} void Print () {for (int i=0;i<k-1;i++) printf ("%d", x[i]);
printf ("%d\n", x[k-1]);
BOOL operator < (const point &a) const {return x[d] < a.x[d];
}} DOT[MAXN], P;
typedef pair<int,int> PR;
#define DI #define ID second priority_queue <PR> heap;
Vector <int> ans;
int build (int l,int r,int now) {if (l>r) return 0;
D = Now;
int mid = (l+r) >>1;
Nth_element (dot+l,dot+mid,dot+r+1); L[mid] = l;
R[mid] = r;
Son[mid][0] = Build (L,mid-1, (now+1)%k);
SON[MID][1] = Build (Mid+1,r, (now+1)%k);
return mid;
#define SQR (x) ((x) * (x)) int Distance (point p1,point P2) {int ret = 0; for (int i=0;i&lT
k;i++) ret = SQR (p1.x[i]-p2.x[i]);
return ret;
} void query (int cur,int now) {if (cur==0) return;
PR nd (Distance (dot[cur],p), cur);
int x = son[cur][0], y = son[cur][1];
if (Dot[cur].x[now]<p.x[now]) swap (x,y);
Query (x, (now+1)%k);
if (Heap.size () <m) Heap.push (ND);
else {if (Nd.di
2, bzoj2648 sjy pendulum pieces
Find the closest point to Manhattan.
Look at the Hzwer program, that Calc judge the query point is closer to that part or more subtle.
But this is a violent insertion. Don't try to rebuild it.
#include <cstdio> #include <cstring> #include <algorithm> using namespace std;
const int MAXN = 1000005;
const int INF = 1E9;
int n,m,d,ans,root;
int son[maxn][2];
struct point {int x[2], mn[2], mx[2];
void Read () {scanf ("%d%d", &x[0],&x[1]);
BOOL operator < (const point &a) const {return x[d]<a.x[d];
}} DOT[MAXN], P;
int Dis (Point p0,point P1) {return abs (P0.x[0]-p1.x[0]) + ABS (p0.x[1]-p1.x[1]);
void Update (int p) {Point L = dot[son[p][0]];
Point R = dot[son[p][1]];
for (int i=0;i<2;i++) {if (son[p][0]) {dot[p].mn[i]=min (Dot[p].mn[i], l.mn[i]);
Dot[p].mx[i]=max (Dot[p].mx[i], l.mx[i]);
} if (son[p][1)) {dot[p].mn[i]=min (Dot[p].mn[i], r.mn[i]);
Dot[p].mx[i]=max (Dot[p].mx[i], r.mx[i]);
"}" int build (int l,int r,int now) {if (l>r) return 0;
D = Now;
int mid = (l+r) >>1;
Nth_element (dot+l,dot+mid,dot+r+1); for (int i=0;i<2;i++) dot[Mid].mn[i] = dot[mid].mx[i] = Dot[mid].x[i];
Son[mid][0] = build (l,mid-1,now^1);
SON[MID][1] = build (mid+1,r,now^1);
Update (mid);
return mid;
} void Insert (int p,int now) {if (Dot[p].x[now]>p.x[now]) {if (son[p][0)) insert (son[p][0],now^1);
else {son[p][0]=++n;
for (int i=0;i<2;i++) dot[n].x[i] = dot[n].mn[i] = Dot[n].mx[i] = P.x[i];
} else {if (son[p][1]) insert (son[p][1],now^1);
else {son[p][1]=++n;
for (int i=0;i<2;i++) dot[n].x[i] = dot[n].mn[i] = Dot[n].mx[i] = P.x[i];
} update (P);
int Calc (point Q) {int ret=0;
for (int i=0;i<2;i++) {Ret+=max (0,q.mn[i]-p.x[i]);
Ret+=max (0,p.x[i]-q.mx[i]);
return ret;
} void query (int p,int now) {int dl=inf, dr=inf;
Ans=min (ans, Dis (dot[p], p));
if (Son[p][0]) Dl=calc (dot[son[p][0]);
if (son[p][1]) Dr=calc (dot[son[p][1]);
if (DL<=DR) {if (ans>dl) query (son[p][0],now^1); if (ans>dr) query (son[p][1],now^1);
else {if (ans>dr) query (son[p][1],now^1);
if (ans>dl) query (son[p][0],now^1);
int main () {freopen ("2648.in", "R", stdin);
Freopen ("2648.out", "w", stdout);
scanf ("%d%d", &n,&m);
for (int i=1;i<=n;i++) dot[i].read ();
Root = Build (1,n,0);
while (m--) {int type;
scanf ("%d", &type);
P.read ();
if (type==1) insert (root,0);
else {ans = INF;
Query (root, 0);
printf ("%d\n", ans);
} return 0; }
3, bzoj4066 simple problem
Look at the topic: This is not CDQ partition.
And then you notice that the space is only 20M.
If you are a card space monster still think this problem can be used CDQ water, you will find this problem forced online ....
The positive solution is kd-tree.
For the problem of the right to point on the board can be directly online maintenance with Kd-tree
But this need to rebuild kd-tree to prevent too whole tree imbalance, you can set a proportional FAC, when the size of a small tree larger than the size of the Shang tree FAC times, the whole Shang tree rebuilt.
I heard someone didn't rebuild the water.
Ask not to say what everybody knows ....
#include <cstdio> #include <cstring> #include <algorithm> using namespace std;
const int MAXN = 200005;
int x1,x2,y1,y2,d;
int n,n,st,ans,rt;
int son[maxn][2];
int POS[MAXN];
struct point {int x[2], mn[2], mx[2], W, sum, size;
void Read () {scanf ("%d%d%d", &x[0],&x[1],&w); X[0]^=ans; X[1]^=ans;
W^=ans;
for (int i=0;i<2;i++) mn[i] = mx[i] = X[i]; sum = w;
size = 1;
BOOL operator < (const point &a) const {return x[d] < a.x[d];
}} DOT[MAXN];
Const double FAC = 0.65;
BOOL CMP (const int &A,CONST int &b) {return dot[a].x[d] < dot[b].x[d];
void Update (int p) {int L = son[p][0], R = son[p][1]; DOT[P].SUM=DOT[P].W;
dot[p].size=1; Dot[p].sum + = Dot[l].sum;
Dot[p].size + = Dot[l].size; Dot[p].sum + = Dot[r].sum;
Dot[p].size + = Dot[r].size;
for (int i=0;i<2;i++) {Dot[p].mn[i] = dot[p].mx[i] = Dot[p].x[i];
if (L) {Dot[p].mn[i] = min (Dot[p].mn[i], dot[l].mn[i]); Dot[p].mx[i] = max (Dot[p].mx[i], dot[l].mx[i]);
} if (R) {Dot[p].mn[i] = min (Dot[p].mn[i], dot[r].mn[i]);
Dot[p].mx[i] = max (Dot[p].mx[i], dot[r].mx[i]);
"}" int build (int l,int r,int now) {if (l>r) return 0;
D = Now;
int mid = (l+r) >>1;
Nth_element (POS+L,POS+MID,POS+R+1,CMP);
Son[pos[mid]][0] = build (l,mid-1,now^1);
SON[POS[MID]][1] = build (mid+1,r,now^1);
Update (Pos[mid]);
return Pos[mid];
} void Dfs (int p) {pos[++st] = p;
if (Son[p][0]) DFS (son[p][0]);
if (son[p][1]) DFS (son[p][1]);
int ins (int p,int now) {if (!p) return N;
int t = (Dot[p].x[now]<=dot[n].x[now]);
if (Dot[son[p][t]].size+1 > (dot[p].size+1) *fac) {pos[st=1]=n; Dfs (P);
p = Build (1,st,now);
else son[p][t] = INS (son[p][t],now^1), update (p);
return p;
int query (int p,int now) {if (p==0) return 0; if (dot[p].mx[0]<x1| |
DOT[P].MN[0]>X2) return 0; if (dot[p].mx[1]<y1| |
Dot[p].mn[1]>y2) return 0; if (dot[P].mn[0]>=x1&&dot[p].mx[0]<=x2&&dot[p].mn[1]>=y1&&dot[p].mx[1]<=y2) return
Dot[p].sum;
int ret = 0; if (dot[p].x[0]>=x1&&dot[p].x[0]<=x2&&dot[p].x[1]>=y1&&dot[p].x[1]<=y2) ret +
= DOT[P].W;
if (Son[p][0]) ret + query (son[p][0],now^1);
if (son[p][1]) ret + query (son[p][1],now^1);
return ret;
int main () {freopen ("4066.in", "R", stdin);
Freopen ("4066.out", "w", stdout);
scanf ("%d", &n);
Ans = 0;
int type;
while (~SCANF ("%d", &type)) {if (type==1) {dot[++n].read ();
RT = INS (rt, 0);
else if (type==2) {scanf ("%d%d", &x1,&y1); X1 ^= ans;
Y1 ^= ans;
scanf ("%d%d", &x2,&y2); X2 ^= ans;
y2 ^= ans;
Ans = query (RT, 0);
printf ("%d\n", ans);
else break;
return 0; }