KDtree真的很妙啊,真的是又好写,作用还多,以后还需更多学习呀.

对于这道题,我们求的是曼哈顿距离的最小值.

而维护的变量和以往是相同的,就是横纵坐标的最小值与最大值.

我们设为一个极为巧妙且玄学的股价函数.

  1. int getdis(int o,int x1,int y1){
  2. int dis = 0;
  3. if(x1 < node[o].minv[0]) dis += node[o].minv[0] - x1;
  4. if(x1 > node[o].maxv[0]) dis += x1 - node[o].maxv[0];
  5. if(y1 < node[o].minv[1]) dis += node[o].minv[1] - y1;
  6. if(y1 > node[o].maxv[1]) dis += y1 - node[o].maxv[1];
  7. return dis;
  8. }
  9. void query(int o,int x1,int y1){
  10. int dn = abs(node[o].p[0] - x1) + abs(node[o].p[1] - y1),dl,dr;
  11. ans = min(ans,dn);
  12. dl = node[o].ch[0] ? getdis(node[o].ch[0],x1,y1) : inf;
  13. dr = node[o].ch[1] ? getdis(node[o].ch[1],x1,y1) : inf;
  14. if(dl < dr) {
  15. if(dl < ans) query(node[o].ch[0],x1,y1);
  16. if(dr < ans) query(node[o].ch[1],x1,y1);
  17. }
  18. else {
  19. if(dr < ans) query(node[o].ch[1],x1,y1);
  20. if(dl < ans) query(node[o].ch[0],x1,y1);
  21. }
  22. }  

设当前矩阵的边界为 (x1,y1),(x2,y2).

那么对于当前要查询的点 $p$ 如果在矩阵外,那么即使是最近距离也是 $p$ 到最近两个矩阵边界的曼哈顿距离和(getdis函数).

我们将上述最理想化距离设为 $w$,即点 $p$ 到矩阵边界的最小距离.

那么,如果点 $p$ 比当前最优解大的话,那么这一棵子树就没有必要查了.

Code:

  1. #include <cstdio>
  2. #include <algorithm>
  3. #include <cstring>
  4. #include <cstdlib>
  5. #define setIO(s) freopen(s".in","r",stdin)
  6. #define maxn 3000000
  7. #define inf 100000000
  8. using namespace std;
  9. namespace KDtree{
  10. int tot;
  11. int d;
  12. int ans;
  13. int n;
  14. int m;
  15. void init(){ tot = n, ans = inf; }
  16. int newnode(){ return ++tot; }
  17. struct Data{
  18. int ch[2],minv[2],maxv[2],w,sum,p[2];
  19. }node[maxn];
  20. bool cmp(Data i,Data j){
  21. return i.p[d] == j.p[d] ? i.p[d^1] < j.p[d^1]: i.p[d] < j.p[d];
  22. }
  23. int isin(int o,int x1,int y1,int x2,int y2){
  24. if(node[o].minv[0]>=x1&&node[o].maxv[0]<=x2&&node[o].minv[1]>=y1&&node[o].maxv[1]<=y2) return 1;
  25. return 0;
  26. }
  27. int isout(int o,int x1,int y1,int x2,int y2){
  28. if(node[o].minv[0] > x2 || node[o].maxv[0] < x1) return 1;
  29. if(node[o].minv[1] > y2 || node[o].maxv[1] < y1) return 1;
  30. return 0;
  31. }
  32. void getmax(int &a,int b){ if( b > a ) a = b; }
  33. void getmin(int &a,int b){ if( b < a ) a = b; }
  34. void pushup(int o,int x){
  35. getmin(node[o].minv[0],node[x].minv[0]);
  36. getmin(node[o].minv[1],node[x].minv[1]);
  37. getmax(node[o].maxv[1],node[x].maxv[1]);
  38. getmax(node[o].maxv[0],node[x].maxv[0]);
  39. node[o].sum += node[x].sum;
  40. }
  41. int build(int l,int r,int o){
  42. int mid = (l + r) >> 1;
  43. d = o ; nth_element(node+l,node+mid,node+r+1,cmp);
  44. node[mid].minv[0] = node[mid].maxv[0] = node[mid].p[0];
  45. node[mid].minv[1] = node[mid].maxv[1] = node[mid].p[1];
  46. node[mid].sum = node[mid].w;
  47. node[mid].ch[0] = node[mid].ch[1] = 0;
  48. if(l < mid) node[mid].ch[0] = build(l,mid - 1,o ^ 1), pushup(mid,node[mid].ch[0]);
  49. if(r > mid) node[mid].ch[1] = build(mid + 1, r, o ^ 1), pushup(mid,node[mid].ch[1]);
  50. return mid;
  51. }
  52. void update(int &o,Data x,int de){
  53. if(!o) {
  54. o = newnode();
  55. node[o].p[0] = node[o].maxv[0] = node[o].minv[0] = x.p[0];
  56. node[o].p[1] = node[o].minv[1] = node[o].maxv[1] = x.p[1];
  57. return;
  58. }
  59. if(x.p[de] < node[o].p[de]) update(node[o].ch[0],x,de^1),pushup(o,node[o].ch[0]);
  60. else update(node[o].ch[1],x,de^1),pushup(o,node[o].ch[1]);
  61. }
  62. int getdis(int o,int x1,int y1){
  63. int dis = 0;
  64. if(x1 < node[o].minv[0]) dis += node[o].minv[0] - x1;
  65. if(x1 > node[o].maxv[0]) dis += x1 - node[o].maxv[0];
  66. if(y1 < node[o].minv[1]) dis += node[o].minv[1] - y1;
  67. if(y1 > node[o].maxv[1]) dis += y1 - node[o].maxv[1];
  68. return dis;
  69. }
  70. void query(int o,int x1,int y1){
  71. int dn = abs(node[o].p[0] - x1) + abs(node[o].p[1] - y1),dl,dr;
  72. ans = min(ans,dn);
  73. dl = node[o].ch[0] ? getdis(node[o].ch[0],x1,y1) : inf;
  74. dr = node[o].ch[1] ? getdis(node[o].ch[1],x1,y1) : inf;
  75. if(dl < dr) {
  76. if(dl < ans) query(node[o].ch[0],x1,y1);
  77. if(dr < ans) query(node[o].ch[1],x1,y1);
  78. }
  79. else {
  80. if(dr < ans) query(node[o].ch[1],x1,y1);
  81. if(dl < ans) query(node[o].ch[0],x1,y1);
  82. }
  83. }
  84. int main(){
  85. scanf("%d%d",&n,&m);
  86. init();
  87. for(int i = 1;i <= n; ++i) scanf("%d%d",&node[i].p[0],&node[i].p[1]);
  88. int root = build(1,n,0);
  89. for(int i = 1;i <= m; ++i) {
  90. int opt,a,b;
  91. scanf("%d%d%d",&opt,&a,&b);
  92. if(opt == 1) {
  93. Data k;
  94. k.p[0] = a,k.p[1] = b;
  95. update(root,k,0);
  96. if(i % 300000 == 0) root = build(1,tot,0);
  97. }
  98. if(opt == 2) {
  99. ans = inf;
  100. query(root,a,b);
  101. printf("%d\n",ans);
  102. }
  103. }
  104. return 0;
  105. }
  106. };
  107. int main(){
  108. //setIO("input");
  109. KDtree::main();
  110. return 0;
  111. }

  

bzoj 2648: SJY摆棋子 KDtree + 替罪羊式重构的更多相关文章

  1. BZOJ 2648: SJY摆棋子 kdtree

    2648: SJY摆棋子 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=2648 Description 这天,SJY显得无聊.在家自己玩 ...

  2. bzoj 2648 SJY摆棋子——KDtree

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2648 第一道KDtree! 学习资料:https://blog.csdn.net/zhl30 ...

  3. BZOJ 2648 SJY摆棋子 ——KD-Tree

    [题目分析] KD-Tree第一题,其实大概就是搜索剪枝的思想,在随机数据下可以表现的非常好NlogN,但是特殊数据下会达到N^2. 精髓就在于估价函数get以及按照不同维度顺序划分的思想. [代码] ...

  4. bzoj 2648: SJY摆棋子&&2716: [Violet 3]天使玩偶 --kdtree

    2648: SJY摆棋子&&2716: [Violet 3]天使玩偶 Time Limit: 20 Sec  Memory Limit: 128 MB Description 这天,S ...

  5. BZOJ 2648: SJY摆棋子

    2648: SJY摆棋子 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 2968  Solved: 1011[Submit][Status][Disc ...

  6. bzoj 2648: SJY摆棋子【KD-tree】

    其实理论上cdq更优 核心是依次取x值.y值的mid作为当前节点,向两边递归建立二叉树,树上维护size:子树大小:mx[0/1]:子树内最大x/y:mn[0/1]:子树内最小x/y:d[0/1]:这 ...

  7. BZOJ 2648: SJY摆棋子(K-D Tree)

    Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 6051  Solved: 2113[Submit][Status][Discuss] Descript ...

  8. bzoj 2648 SJY摆棋子 kd树

    题目链接 初始的时候有一些棋子, 然后给两种操作, 一种是往上面放棋子. 另一种是给出一个棋子的位置, 问你离它最近的棋子的曼哈顿距离是多少. 写了指针版本的kd树, 感觉这个版本很好理解. #inc ...

  9. BZOJ 2648 SJY摆棋子(KD Tree)

    http://www.lydsy.com/JudgeOnline/problem.php?id=2648 题意: 思路: KDtree模板题. 参考自http://www.cnblogs.com/ra ...

随机推荐

  1. word2016如何英汉互译

    1.如果是一篇英文文档且是pdf格式,可以用word2016打开直接转化成了word,就算不是会员也可以的,在此附上16版的光盘安装包,可以百度自行下载 (链接:https://pan.baidu.c ...

  2. 【JavaScript框架封装】使用Prototype给Array,String,Function对象的方法扩充

    /* * @Author: 我爱科技论坛* @Time: 20180705 * @Desc: 实现一个类似于JQuery功能的框架* V 1.0: 实现了基础框架.事件框架.CSS框架.属性框架.内容 ...

  3. Gym-101615D Rainbow Roads 树的DFS序 差分数组

    题目链接:https://cn.vjudge.net/problem/Gym-101615D 题意 给一棵树,每个边权表示一种颜色. 现定义一条彩虹路是每个颜色不相邻的路. 一个好点是所有从该节点开始 ...

  4. [Libre 6282] 数列分块入门 6 (分块)

    原题:传送门 code: //By Menteur_Hxy #include<cstdio> #include<iostream> #include<algorithm& ...

  5. IIS部署ASP.NET网站后提示只有在配置文件或 Page 指令中将 enableSessionState 设置为 true 时,才能使用会话状态...

    今天,在IIS上部署网站后,出现了下面错误: 只有在配置文件或 Page 指令中将 enableSessionState 设置为 true 时,才能使用会话状态.还请确保在应用程序配置的 <sy ...

  6. 【 ACM-ICPC 2018 沈阳赛区网络预赛 D】Made In Heaven

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 点可以重复走的k短路. [代码] #include <bits/stdc++.h> #define LL long lo ...

  7. UVA11752 The Super Powers

    /* UVA11752 The Super Powers https://vjudge.net/contest/153365#problem/Y 数论 注意a^n=b要用除法求,并且求得的n比实际大1 ...

  8. hdu 1163

    别人的代码开始自己不知道什么数论解法: ab*ab=(a*10+b)(a*10+b)=a^2*100+2ab*10+b^2 所以the root digital=(a+b)*(a+b): 而数论中的定 ...

  9. 轻松学习JavaScript十二:JavaScript基于面向对象之创建对象(一)

    这一次我们深入的学习一下JavaScript面向对象技术,在学习之前,必要的说明一下一些面向对象的一些术语. 这也是全部面对对象语言所拥有的共同点.有这样几个面向对象术语: 对象 ECMA-262把对 ...

  10. jQuery幻灯片插件Owl Carousel

    简介 Owl Carousel 是一个强大.实用但小巧的 jQuery 幻灯片插件,它具有一下特点: 兼容所有浏览器 支持响应式 支持 CSS3 过度 支持触摸事件 支持 JSON 及自定义 JSON ...