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

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

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

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

int getdis(int o,int x1,int y1){
int dis = 0;
if(x1 < node[o].minv[0]) dis += node[o].minv[0] - x1;
if(x1 > node[o].maxv[0]) dis += x1 - node[o].maxv[0];
if(y1 < node[o].minv[1]) dis += node[o].minv[1] - y1;
if(y1 > node[o].maxv[1]) dis += y1 - node[o].maxv[1];
return dis;
}
void query(int o,int x1,int y1){
int dn = abs(node[o].p[0] - x1) + abs(node[o].p[1] - y1),dl,dr;
ans = min(ans,dn);
dl = node[o].ch[0] ? getdis(node[o].ch[0],x1,y1) : inf;
dr = node[o].ch[1] ? getdis(node[o].ch[1],x1,y1) : inf;
if(dl < dr) {
if(dl < ans) query(node[o].ch[0],x1,y1);
if(dr < ans) query(node[o].ch[1],x1,y1);
}
else {
if(dr < ans) query(node[o].ch[1],x1,y1);
if(dl < ans) query(node[o].ch[0],x1,y1);
}
}  

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

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

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

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

Code:

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#define setIO(s) freopen(s".in","r",stdin)
#define maxn 3000000
#define inf 100000000
using namespace std;
namespace KDtree{
int tot;
int d;
int ans;
int n;
int m;
void init(){ tot = n, ans = inf; }
int newnode(){ return ++tot; }
struct Data{
int ch[2],minv[2],maxv[2],w,sum,p[2];
}node[maxn];
bool cmp(Data i,Data j){
return i.p[d] == j.p[d] ? i.p[d^1] < j.p[d^1]: i.p[d] < j.p[d];
}
int isin(int o,int x1,int y1,int x2,int y2){
if(node[o].minv[0]>=x1&&node[o].maxv[0]<=x2&&node[o].minv[1]>=y1&&node[o].maxv[1]<=y2) return 1;
return 0;
}
int isout(int o,int x1,int y1,int x2,int y2){
if(node[o].minv[0] > x2 || node[o].maxv[0] < x1) return 1;
if(node[o].minv[1] > y2 || node[o].maxv[1] < y1) return 1;
return 0;
}
void getmax(int &a,int b){ if( b > a ) a = b; }
void getmin(int &a,int b){ if( b < a ) a = b; }
void pushup(int o,int x){
getmin(node[o].minv[0],node[x].minv[0]);
getmin(node[o].minv[1],node[x].minv[1]);
getmax(node[o].maxv[1],node[x].maxv[1]);
getmax(node[o].maxv[0],node[x].maxv[0]);
node[o].sum += node[x].sum;
}
int build(int l,int r,int o){
int mid = (l + r) >> 1;
d = o ; nth_element(node+l,node+mid,node+r+1,cmp);
node[mid].minv[0] = node[mid].maxv[0] = node[mid].p[0];
node[mid].minv[1] = node[mid].maxv[1] = node[mid].p[1];
node[mid].sum = node[mid].w;
node[mid].ch[0] = node[mid].ch[1] = 0;
if(l < mid) node[mid].ch[0] = build(l,mid - 1,o ^ 1), pushup(mid,node[mid].ch[0]);
if(r > mid) node[mid].ch[1] = build(mid + 1, r, o ^ 1), pushup(mid,node[mid].ch[1]);
return mid;
}
void update(int &o,Data x,int de){
if(!o) {
o = newnode();
node[o].p[0] = node[o].maxv[0] = node[o].minv[0] = x.p[0];
node[o].p[1] = node[o].minv[1] = node[o].maxv[1] = x.p[1];
return;
}
if(x.p[de] < node[o].p[de]) update(node[o].ch[0],x,de^1),pushup(o,node[o].ch[0]);
else update(node[o].ch[1],x,de^1),pushup(o,node[o].ch[1]);
}
int getdis(int o,int x1,int y1){
int dis = 0;
if(x1 < node[o].minv[0]) dis += node[o].minv[0] - x1;
if(x1 > node[o].maxv[0]) dis += x1 - node[o].maxv[0];
if(y1 < node[o].minv[1]) dis += node[o].minv[1] - y1;
if(y1 > node[o].maxv[1]) dis += y1 - node[o].maxv[1];
return dis;
}
void query(int o,int x1,int y1){
int dn = abs(node[o].p[0] - x1) + abs(node[o].p[1] - y1),dl,dr;
ans = min(ans,dn);
dl = node[o].ch[0] ? getdis(node[o].ch[0],x1,y1) : inf;
dr = node[o].ch[1] ? getdis(node[o].ch[1],x1,y1) : inf;
if(dl < dr) {
if(dl < ans) query(node[o].ch[0],x1,y1);
if(dr < ans) query(node[o].ch[1],x1,y1);
}
else {
if(dr < ans) query(node[o].ch[1],x1,y1);
if(dl < ans) query(node[o].ch[0],x1,y1);
}
}
int main(){
scanf("%d%d",&n,&m);
init();
for(int i = 1;i <= n; ++i) scanf("%d%d",&node[i].p[0],&node[i].p[1]);
int root = build(1,n,0);
for(int i = 1;i <= m; ++i) {
int opt,a,b;
scanf("%d%d%d",&opt,&a,&b);
if(opt == 1) {
Data k;
k.p[0] = a,k.p[1] = b;
update(root,k,0);
if(i % 300000 == 0) root = build(1,tot,0);
}
if(opt == 2) {
ans = inf;
query(root,a,b);
printf("%d\n",ans);
}
}
return 0;
}
};
int main(){
//setIO("input");
KDtree::main();
return 0;
}

  

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. BZOJ 1602: [Usaco2008 Oct]牧场行走 倍增裸题

    Description N头牛(2<=n<=1000)别人被标记为1到n,在同样被标记1到n的n块土地上吃草,第i头牛在第i块牧场吃草. 这n块土地被n-1条边连接. 奶牛可以在边上行走, ...

  2. Python数据分析4------------数据变换

    1.简单变换: 开方.平方.对数等 2.数据规范化: (1)离差标准化(最小最大标准化):消除量纲(单位)影响以及变异大小因素的影响. x1=(x-min)/(max-min) 代码:data1=(d ...

  3. Centos文件查看命令字符

    文件(夹)查看类命令 ls--显示指定目录下内容 说明:ls 显示结果以不同的颜色来区分文件类别.蓝色代表目录,灰色代表普通文件,绿色代表可执行文件,红色代表压缩文件,浅蓝色代表链接文件. -a--- ...

  4. 启动 Appium 自带模拟器

    1.先在sclipse中新建并打开一个设备 2.启动appium 3.安装apk 打开cmd  并在sdk安装目录的tools文件夹下输入安装命令adb install xxx.apk(在这之前需要把 ...

  5. [MongoDB实战]Part1 起步

    本书的这部分对MongoDB进行了一个大致的简介.包括了Javascript Shell和Ruby驱动,这俩都有例子 在第一章,我们将了解到MongoDB的历史,设计目的和实际使用的场景.我们还将了解 ...

  6. [HTML5]构建离线web应用程序

    1.检查浏览器是否支持缓存 if(window.applicationCache){ //TODO } 2.在html中加入manifest特性 <html manifest="app ...

  7. POJ 3737

    第一道三分题,有模板 #define eps 10e-6 double cal(){}//计算题目所需要的值 while(l+eps<r) { m1=l+(r-l)/3; m2=r-(r-l)/ ...

  8. 菜鸟的mongoDB学习---(六)MongoDB 索引

    MongoDB 索引 ps:大概有半个月木有更新了,因为前一阶段的出差和这几天突然来的项目.导致上网时间急剧降低,实在是sorry,以后预计会好一点. 索引通常可以极大的提高查询的效率.假设没有索引. ...

  9. OC第三天(内存管理)

    内存管理: 1.作用范围: 不论什么继承了NSObject的对象,堆基本数据类型无效如:int a ,float price;;等 2.原理: 每一个对象内部都保存了一个与之相关的整数,称为引用计数器 ...

  10. jQuery Video Extend

    HTML5视频扩展插件 能够加入Logo 加入标记 用法: 下载:jquery-video-extend <script src="js/jquery-2.1.4.min.js&quo ...