博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【BZOJ】2648: SJY摆棋子 & 2716: [Violet 3]天使玩偶(kdtree)
阅读量:6275 次
发布时间:2019-06-22

本文共 3302 字,大约阅读时间需要 11 分钟。

双倍经验题。。。

kdtree裸题吧。。。。。今天学了下kdtree。。。感觉挺简单的。。。。

其实就是对几何图形进行剖分建树,而特殊在于,x和y轴轮流剖。。。。这样可以提供很好的性质以便于查找。。。

(一开始脑补了个treap代替kdtree。。。。。显然我脑残了。。。。写到一半发现这是不能旋转的。。。。。

(然后又脑补了下。。。。这货如果和孙子(儿子的儿子)可以旋转。。。。。。。。因为这货的节点类似红黑树。。。但是蒟蒻我太弱从来没写过红黑树。。。

很好的资料(概念脑补):

一些参考代码(虽然说完全没按照这样写):

说一下怎么查找。

首先这是曼哈顿距离。。和欧几里得距离不同。。。如果欧几里得那么简单多了。。

我们需要维护极值(即能包围所有子树包括自己的点的一个矩形的四个顶点):

如果要查找的点在矩形内,那么进入查找。

如果在矩形外,那么计算出查找点到矩形的曼哈顿距离,判断是否小于当前最优解,如果是,进入搜索。

(或许还能优化,因为一开始我的想法和这个不怎么一样。。我觉得。。递归进入两棵子树中其中一棵后(按x或y排序而不是找极值),然后判断最优解是否能从左子树的某个点越过当前根的分割线。。。。。如果是,就进入。。。

然后就没了。。。

留下的坑:欧几里得的没写过。。。删除操作没写过(觉对要斯巴达。。。。想写成平衡树(强迫症系列

#include 
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;typedef long long ll;#define rep(i, n) for(int i=0; i<(n); ++i)#define for1(i,a,n) for(int i=(a);i<=(n);++i)#define for2(i,a,n) for(int i=(a);i<(n);++i)#define for3(i,a,n) for(int i=(a);i>=(n);--i)#define for4(i,a,n) for(int i=(a);i>(n);--i)#define CC(i,a) memset(i,a,sizeof(i))#define read(a) a=getint()#define print(a) printf("%d", a)#define dbg(x) cout << (#x) << " = " << (x) << endl#define error(x) (!(x)?puts("error"):0)#define rdm(x, i) for(int i=ihead[x]; i; i=e[i].next)inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }const int N=2000005, oo=~0u>>1;struct node *null;struct node { node *c[2]; int mx[2], mn[2], p[2]; void upd(node *x) { if(x==null) return; mx[0]=max(mx[0], x->mx[0]); mx[1]=max(mx[1], x->mx[1]); mn[0]=min(mn[0], x->mn[0]); mn[1]=min(mn[1], x->mn[1]); } int getdis(node *x) { int ret=0; ret+=max(x->p[0]-mx[0], 0); ret+=max(x->p[1]-mx[1], 0); ret+=max(mn[0]-x->p[0], 0); ret+=max(mn[1]-x->p[1], 0); return ret; } void init(int x, int y) { p[0]=mx[0]=mn[0]=x; p[1]=mx[1]=mn[1]=y; c[0]=c[1]=null; } int dis(node *x) { return abs(p[0]-x->p[0])+abs(p[1]-x->p[1]); }}*root, T[N], *Tcnt=T;node *newnode(int x=0, int y=0) { Tcnt->init(x, y); return Tcnt++; }void init() { null=newnode(); null->c[0]=null->c[1]=null; root=null; }void insert(node *&x, node *y, bool f) { if(x==null) { x=y; return; } bool d=x->p[f]
p[f]; x->upd(y); insert(x->c[d], y, !f);}void ins(int x, int y) { insert(root, newnode(x, y), 0); }void ask(node *x, node *y, int &ans) { ans=min(ans, x->dis(y)); int d[2]; d[0]=x->c[0]==null?oo:x->c[0]->getdis(y); d[1]=x->c[1]==null?oo:x->c[1]->getdis(y); bool f=d[0]>d[1]; if(d[f]==oo) return; ask(x->c[f], y, ans); if(d[!f]
c[!f], y, ans);}int ask(int x, int y) { int ret=oo; static node r; r.p[0]=x; r.p[1]=y; ask(root, &r, ret); return ret;}int main() { init(); int n=getint(), m=getint(); rep(i, n) { int x=getint(), y=getint(); ins(x, y); } while(m--) { int t=getint(), x=getint(), y=getint(); if(t==2) printf("%d\n", ask(x, y)); else ins(x, y); } return 0;}

  

 


 

 

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可以过

 

Source

转载地址:http://darpa.baihongyu.com/

你可能感兴趣的文章
基于容器服务的持续集成与云端交付(三)- 从零搭建持续交付系统
查看>>
《算法基础:打开算法之门》一3.4 归并排序
查看>>
高德开放平台开放源代码 鼓励开发者创新
查看>>
《高并发Oracle数据库系统的架构与设计》一2.5 索引维护
查看>>
《Exchange Server 2010 SP1/SP2管理实践》——2.4 部署外部网络环境
查看>>
Firefox 是 Pwn2own 2014 上攻陷次数最多的浏览器
查看>>
《Java多线程编程核心技术》——1.8节暂停线程
查看>>
阿里感悟(十八)- 应届生Review
查看>>
《计算广告:互联网商业变现的市场与技术》一第一部分 在线广告市场与背景...
查看>>
话说模式匹配(5) for表达式中的模式匹配
查看>>
《锋利的SQL(第2版)》——1.7 常用函数
查看>>
《Arduino家居安全系统构建实战》——1.5 介绍用于机器学习的F
查看>>
jquery中hover()的用法。简单粗暴
查看>>
线程管理(六)等待线程的终结
查看>>
《HTML5 2D游戏编程核心技术》——第3章,第3.7节反转滚动方向
查看>>
spring boot集成mongodb最简单版
查看>>
DELL EqualLogic PS存储数据恢复全过程整理
查看>>
《Node.js入门经典》一2.3 安装模块
查看>>
《Java 开发从入门到精通》—— 2.5 技术解惑
查看>>
又是神经网络!还能用来盗取XX女演员信息
查看>>