【BZOJ2648】【kd_tree】SJY摆棋子

Description

这天,SJY显得无聊。在家自己玩。在一个棋盘上,有N个黑色棋子。他每次要么放到棋盘上一个黑色棋子,要么放上一个白色棋子,如果是白色棋子,他会找出距离这个白色棋子最近的黑色棋子。此处的距离是 曼哈顿距离 即(|x1-x2|+|y1-y2|) 。现在给出N<=500000个初始棋子。和M<=500000个操作。对于每个白色棋子,输出距离这个白色棋子最近的黑色棋子的距离。同一个格子可能有多个棋子。

Input

第一行两个数 N M

以后M行,每行3个数 t x y

如果t=1 那么放下一个黑色棋子

如果t=2 那么放下一个白色棋子

Output

对于每个T=2 输出一个最小距离

Sample Input

2 3

1 1

2 3

2 1 2

1 3 3

2 4 2

Sample Output

1

2

HINT

kdtree可以过

【分析】

大家都知道kd_tree是什么吧,恩

就这样了..好吧,kd_tree一种空间树..看代码就知道了

  1 /*
  2 唐代李白
  3 《江夏别宋之悌》
  4 楚水清若空,遥将碧海通。人分千里外,兴在一杯中。
  5 谷鸟吟晴日,江猿啸晚风。平生不下泪,于此泣无穷.
  6 */
  7 #include <iostream>
  8 #include <cstdio>
  9 #include <algorithm>
 10 #include <cstring>
 11 #include <vector>
 12 #include <utility>
 13 #include <iomanip>
 14 #include <string>
 15 #include <cmath>
 16 #include <queue>
 17 #include <assert.h>
 18 #include <map>
 19 #include <ctime>
 20 #include <cstdlib>
 21 #include <stack>
 22 #include <set>
 23 #define LOCAL
 24 const int INF = 0x7fffffff;
 25 const int MAXN = 100000  + 10;
 26 const int maxnode = 20000 * 2 + 200000 * 20;
 27 const int MAXM = 50000 + 10;
 28 const int MAX = 100000000;
 29 using namespace std;
 30 struct Node{//kd_tree
 31    int d[2], l, r;
 32    int Max[2], Min[2];
 33 }t[1000000 + 10],tmp;
 34
 35 int n,m,root,cmp_d;
 36 int k1, k2, k3, Ans;
 37
 38 bool cmp(Node a, Node b){return (a.d[cmp_d]<b.d[cmp_d]) || ((a.d[cmp_d] == b.d[cmp_d]) && (a.d[!cmp_d] < b.d[!cmp_d]));}
 39 void update(int p){
 40      if (t[p].l){
 41         //左边最大的横坐标值
 42         t[p].Max[0] = max(t[p].Max[0], t[t[p].l].Max[0]);
 43         t[p].Min[0] = min(t[p].Min[0], t[t[p].l].Min[0]);
 44         t[p].Max[1] = max(t[p].Max[1], t[t[p].l].Max[1]);
 45         t[p].Min[1] = min(t[p].Min[1], t[t[p].l].Min[1]);
 46      }
 47      if (t[p].r){
 48         t[p].Max[0] = max(t[p].Max[0], t[t[p].r].Max[0]);
 49         t[p].Min[0] = min(t[p].Min[0], t[t[p].r].Min[0]);
 50         t[p].Max[1] = max(t[p].Max[1], t[t[p].r].Max[1]);
 51         t[p].Min[1] = min(t[p].Min[1], t[t[p].r].Min[1]);
 52      }
 53      return;
 54 }
 55 //d是横竖切..
 56 int build(int l, int r, int D){
 57     int mid = (l + r) / 2;
 58     cmp_d = D;
 59     //按照cmp的比较顺序在l到r中找到第mid大的元素
 60     nth_element(t + l + 1, t + mid + 1, t + r + 1, cmp);
 61     t[mid].Max[0] = t[mid].Min[0] = t[mid].d[0];
 62     t[mid].Max[1] = t[mid].Min[1] = t[mid].d[1];
 63     //递归建树
 64     if (l != mid) t[mid].l = build(l, mid - 1, D ^ 1);
 65     if (r != mid) t[mid].r = build(mid + 1, r, D ^ 1);
 66     update(mid);
 67     return mid;
 68 }
 69 void insert(int now){
 70      int D = 0, p = root;//D还是表示方向
 71      while (1){
 72            //边下传边更新
 73            t[p].Max[0] = max(t[p].Max[0], t[now].Max[0]);
 74            t[p].Min[0] = min(t[p].Min[0], t[now].Min[0]);
 75            t[p].Max[1] = max(t[p].Max[1], t[now].Max[1]);
 76            t[p].Min[1] = min(t[p].Min[1], t[now].Min[1]);
 77            //有没有点线段树的感觉..
 78            if (t[now].d[D] >= t[p].d[D]){
 79               if (t[p].r == 0){
 80                  t[p].r = now;
 81                  return;
 82               }else p = t[p].r;
 83            }else{
 84               if (t[p].l == 0){
 85                  t[p].l = now;
 86                  return;
 87               }else p = t[p].l;
 88            }
 89            D = D ^ 1;
 90      }
 91      return;
 92 }
 93 int ABS(int x) {return x < 0? -x : x;}
 94 //dist越小代表越趋近?
 95 int dist(int p1, int px, int py){
 96     int dist = 0;
 97     if (px < t[p1].Min[0]) dist += t[p1].Min[0] - px;
 98     if (px > t[p1].Max[0]) dist += px - t[p1].Max[0];
 99     if (py < t[p1].Min[1]) dist += t[p1].Min[1] - py;
100     if (py > t[p1].Max[1]) dist += py - t[p1].Max[1];
101     return dist;
102 }
103 void ask(int p){
104    int dl, dr, d0;
105    //哈密顿距离
106    d0=ABS(t[p].d[0] - k2) + ABS(t[p].d[1] - k3);
107    if(d0 < Ans) Ans = d0;
108    if(t[p].l) dl = dist(t[p].l, k2, k3); else dl = 0x7f7f7f7f;
109    if(t[p].r) dr = dist(t[p].r, k2, k3); else dr = 0x7f7f7f7f;
110    //应该是一个启发式的过程。
111    if(dl < dr){
112        if(dl < Ans) ask(t[p].l);
113        if(dr < Ans) ask(t[p].r);
114    }else{
115        if(dr < Ans) ask(t[p].r);
116        if(dl < Ans) ask(t[p].l);
117    }
118 }
119
120 void init(){
121      //假设0为横坐标
122      scanf("%d%d", &n, &m);
123      for (int i = 1; i <= n; i++)
124      scanf("%d%d", &t[i].d[0], &t[i].d[1]);
125      root = build(1, n, 0);
126 }
127 void work(){
128      for (int i = 1; i <= m ;i++){
129          scanf("%d%d%d", &k1, &k2, &k3);
130          if (k1 == 1){//黑棋
131             ++n;
132             t[n].Max[0] = t[n].Min[0] = t[n].d[0] = k2;
133             t[n].Max[1] = t[n].Min[1] = t[n].d[1] = k3;
134             insert(n);
135          }else{
136             Ans = 0x7f7f7f7f;
137             ask(root);
138             printf("%d\n", Ans);
139          }
140      }
141 }
142
143 int main(){
144
145    init();
146    work();
147    return 0;
148 }

时间: 2024-10-10 20:59:00

【BZOJ2648】【kd_tree】SJY摆棋子的相关文章

【BZOJ2648】SJY摆棋子 [KD-tree]

SJY摆棋子 Time Limit: 20 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description 这天,SJY显得无聊.在家自己玩.在一个棋盘上,有N个黑色棋子.他每次要么放到棋盘上一个黑色棋子,要么放上一个白色棋子,如果是白色棋子,他会找出距离这个白色棋子最近的黑色棋子.此处的距离是 曼哈顿距离 即(|x1-x2|+|y1-y2|) .现在给出N个初始棋子,和M个操作.对于每个白色棋子,输出距离这个白色棋子最近的黑色棋子的

[bzoj2648/2716]SJY摆棋子

平面上有n个点,要求支持插入一个点和查询一个点的最近点距离 n,m<=500000 用kdtree实现,但是复杂度貌似没法保证.....下次加一个替罪羊重建试试. #include<iostream> #include<cstdio> #include<algorithm> #define INF 2000000000 #define MN 1000000 using namespace std; inline int read() { int x = 0 , f

BZOJ 2648(SJY摆棋子-KD_Tree)

2648: SJY摆棋子 Time Limit: 20 Sec  Memory Limit: 128 MB Submit: 1180  Solved: 391 [Submit][Status][Discuss] Description 这天,SJY显得无聊.在家自己玩.在一个棋盘上,有N个黑色棋子.他每次要么放到棋盘上一个黑色棋子,要么放上一个白色棋子,如果是白色棋子,他会找出距离这个白色棋子最近的黑色棋子.此处的距离是 曼哈顿距离 即(|x1-x2|+|y1-y2|) .现在给出N<=5000

【BZOJ-2648&amp;2716】SJY摆棋子&amp;天使玩偶 KD Tree

2648: SJY摆棋子 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 2459  Solved: 834[Submit][Status][Discuss] Description 这天,SJY显得无聊.在家自己玩.在一个棋盘上,有N个黑色棋子.他每次要么放到棋盘上一个黑色棋子,要么放上一个白色棋子,如果是白色棋子,他会找出距离这个白色棋子最近的黑色棋子.此处的距离是 曼哈顿距离 即(|x1-x2|+|y1-y2|) .现在给出N<=500000

SJY摆棋子&amp;&amp;[Violet 3]天使玩偶

SJY摆棋子 https://www.lydsy.com/JudgeOnline/problem.php?id=2648 [Violet 3]天使玩偶 https://www.lydsy.com/JudgeOnline/problem.php?id=2716 参考博客:https://blog.csdn.net/Littlewhite520/article/details/78284697 KDtree模板题,带插入 1 #include<iostream> 2 #include<cst

Bzoj2648 SJY摆棋子

Time Limit: 20 Sec  Memory Limit: 128 MB Submit: 3128  Solved: 1067 Description 这天,SJY显得无聊.在家自己玩.在一个棋盘上,有N个黑色棋子.他每次要么放到棋盘上一个黑色棋子,要么放上一个白色棋子,如果是白色棋子,他会找出距离这个白色棋子最近的黑色棋子.此处的距离是 曼哈顿距离 即(|x1-x2|+|y1-y2|) .现在给出N<=500000个初始棋子.和M<=500000个操作.对于每个白色棋子,输出距离这个

[bzoj2648]SJY摆棋子(带插入kd-tree)

解题关键:带插入kdtree模板题. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define N 1000005 #define inf (1<<30) using namespace std; int n,m,dim,rt,ans; struct node{int p[2],x[2],y[2];}a[N]; bool cmp(node x

【kd-tree】bzoj2648 SJY摆棋子

#include<cstdio> #include<cmath> #include<algorithm> using namespace std; #define N 500001 #define INF 2147483647 #define KD 2//ά¶ÈÊý int qp[KD],disn; int n,root; bool dn; struct Node { int minn[KD],maxx[KD],p[KD]; int ch[2]; void Init(

【bzoj2648&amp;bzoj2716】[Violet3]天使玩偶&amp;SJY摆棋子【kd树】

1BK捌脊允4iyo松纲06http://weibo.com/u/6264971116 382u60L86vl戎导屯http://www.docin.com/nqra496 u23j6h0敢d缴遮ahttp://www.facebolw.com/space/2104191 86褐2咕6镜y米0uhttp://huiyi.docin.com/sina_6352810924 160hA坷Yk闭苫6尾ehttp://shequ.docin.com/sina_6267166088 侍4E0pf范星17南