BZOJ1941Hide and Seek
做KD_tree的入门题。
问题就是求出任意一个点距其他点的最大曼哈顿距离和最小曼哈顿距离差,然后对其取min即可。
这个东西就是KD_tree可以轻松解决的了。
下面总结一下做KD_tree(不带修)的心得。
KD_tree本质上是一颗搜索树,实际上将所有可能的决策集合不重不漏的划分了出来,而我们要做的就是剪枝。
其实建KD_tree的过程就是将一个平面划分成若干小块,即子问题,来方便我们查找,一般的KD_tree需要以下内容:
首先左右儿子是必备的。然后注意一个非常重要的事情,我们划分的时候是有基准的,我们建立KD_tree的时候,每一个节点都包含着一个真实的点,我称之为基准点(BP),我们递归进行的时候就是利用BP来更新ans。接着就是剪枝用的组件,在本题中,我们维护矩形的4个边界,只有我们用估价函数算出的值比较优秀的时候我们才向下进行,因为估价函数考虑的是最优情况,如果这种可能性很小的最优情况都不满足,那么别的条件就更没用了,我们不需要进入这颗子树。
接着一个New函数是KD_tree建立的基础,我们将上述组件全部赋好初值,(因为野针确实可pia)。
pushup函数就如同线段树一般,我们维护的信息大多可以“区间”合并。
cal估价函数是KD_tree的灵魂,否则KD_tree有时就是大暴力(其实加了剪枝也像暴力)。
接着开始快乐建树。
r>l就return,开点,换now,nth_element找中位,维护自身信息,递归左右儿子,pushup,建完收工。
然后进行快乐查询。
空指针,return,用当前节点的BP尝试更新答案,求出左右儿子估价值,先跑更优的,因为跑完它以后那个次优的可能就不用跑了。
完成。
#include<bits/stdc++.h>
#define null NULL
using namespace std;
const int N=;
const int inf=0x7fffffff;
inline int read(){
int sum(),f();char x=getchar();
while(x<''||x>''){
if(x=='-') f=-;
x=getchar();
}while(x>=''&&x<=''){
sum=sum*+x-'';
x=getchar();
}return sum*f;
}
inline int abs_(int x){
return x<?-x:x;
}
inline int min_(int x,int y){
return x<y?x:y;
}
inline int max_(int x,int y){
return x>y?x:y;
}
int now,n,ans=inf,tot,Maxans,Minans;
struct node{
int x[];//x,y坐标
}poi[N];
bool comp(node a,node b){
return a.x[now]<b.x[now];
}
inline int Mhtdis(node a,node b){
return abs_(a.x[]-b.x[])+abs_(a.x[]-b.x[]);
}
struct Kd_tree{
Kd_tree *ch[];
node BP;
int minv[],maxv[];
inline void New(node a){
BP=a;
minv[]=maxv[]=a.x[];
minv[]=maxv[]=a.x[];
ch[]=ch[]=null;
}
inline void pushup(){
if(ch[]){
minv[]=min_(minv[],ch[]->minv[]);
maxv[]=max_(maxv[],ch[]->maxv[]);
minv[]=min_(minv[],ch[]->minv[]);
maxv[]=max_(maxv[],ch[]->maxv[]);
}
if(ch[]){
minv[]=min_(minv[],ch[]->minv[]);
maxv[]=max_(maxv[],ch[]->maxv[]);
minv[]=min_(minv[],ch[]->minv[]);
maxv[]=max_(maxv[],ch[]->maxv[]);
}
}
inline int cal_min(node a){
return max_(minv[]-a.x[],)+max_(a.x[]-maxv[],)
+max_(minv[]-a.x[],)+max_(a.x[]-maxv[],);
}
inline int cal_max(node a){
return max_(abs_(a.x[]-minv[]),abs_(a.x[]-maxv[]))
+max_(abs_(a.x[]-minv[]),abs_(a.x[]-maxv[]));
}
}*root,pool[N];
void build(Kd_tree *&p,int l,int r,int d){
if(l>r) return ;
p=pool+(tot++); now=d;
int mid=l+r>>;
nth_element(poi+l,poi+mid,poi+r,comp);
p->New(poi[mid]);
build(p->ch[],l,mid-,d^);
build(p->ch[],mid+,r,d^);
p->pushup();
}
void query_max(Kd_tree *p,node rec){
if(p==null) return ;
Maxans=max_(Mhtdis(p->BP,rec),Maxans);
int dis[]={p->ch[]==null?:p->ch[]->cal_max(rec),
p->ch[]==null?:p->ch[]->cal_max(rec)};
int first=dis[]>dis[]?:;
if(dis[first]>Maxans) query_max(p->ch[first],rec);
if(dis[first^]>Maxans) query_max(p->ch[first^],rec);
}
void query_min(Kd_tree *p,node rec){
if(p==null) return ;
if(Mhtdis(p->BP,rec))
Minans=min_(Mhtdis(p->BP,rec),Minans);
int dis[]={p->ch[]==null?inf:p->ch[]->cal_min(rec),
p->ch[]==null?inf:p->ch[]->cal_min(rec)};
int first=dis[]<dis[]?:;
if(dis[first]<Minans) query_min(p->ch[first],rec);
if(dis[first^]<Minans) query_min(p->ch[first^],rec);
}
inline int query_max(node rec){
Maxans=;
query_max(root,rec);
return Maxans;
}
inline int query_min(node rec){
Minans=inf;
query_min(root,rec);
return Minans;
}
int main(){
n=read();
for(int i=;i<=n;++i){
poi[i].x[]=read();
poi[i].x[]=read();
}
build(root,,n,);
for(int i=;i<=n;++i)
ans=min_(ans,query_max(poi[i])-query_min(poi[i]));
printf("%d",ans);
return ;
}
(论循环展开的优越性)
BZOJ1941Hide and Seek的更多相关文章
- 【SDOI2010题集整合】BZOJ1922~1927&1941&1951&1952&1972&1974&1975
BZOJ1922大陆争霸 思路:带限制的单源最短路 限制每个点的条件有二,路程和最早能进入的时间,那么对两个值一起限制跑最短路,显然想要访问一个点最少满足max(dis,time) 那么每次把相连的点 ...
- 【Android】 修复ijkPlayer进行m3u8 hls流播放时seek进度条拖动不准确的问题
项目中使用的播放器是ijkPlayer,发现播放切片特点的hls流(m3u8格式的视频)拖动seekBar的时候会莫名的跳转或者seek不到准确的位置,发现网友也遇到了同样的问题,ijk的开发者也说明 ...
- POJ 2752 Seek the Name, Seek the Fame [kmp]
Seek the Name, Seek the Fame Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 17898 Ac ...
- Index Seek和Index Scan的区别
Index Seek是Sql Server执行查询语句时利用建立的索引进行查找,索引是B树结构,Sql Server先查找索引树的根节点,一级一级向下查找,在查找到相应叶子节点后,取出叶子节点的数据. ...
- 【BZOJ-1941】Hide and Seek KD-Tree
1941: [Sdoi2010]Hide and Seek Time Limit: 16 Sec Memory Limit: 162 MBSubmit: 830 Solved: 455[Submi ...
- PYTHON seek()tell()语句
print(f.tell()) # 显示当前位置 f.seek(0) #回到某一起点
- stream的seek方法实例
using (FileStream outStream = new FileStream(@"D:\12.txt", FileMode.Open)) { using (FileSt ...
- ai seek
原文地址链接:http://gamedevelopment.tutsplus.com/tutorials/understanding-steering-behaviors-seek--gamedev- ...
- seek指针大文件上传
package mainimport ( // "bufio" "fmt" "github.com/axgle/mahonia&qu ...
随机推荐
- Sharding-JDBC介绍
Sharding-JDBC是当当应用框架ddframe中,从关系型数据库模块dd-rdb中分离出来的数据库水平分片框架,实现透明化数据库分库分表访问.Sharding-JDBC是继dubbox和ela ...
- 这个一个对ES6多个异步处理的并发继发思想的总结和理解
1.首先我们需要理解的是js中for循环.forEach循环.map循环的一些差异性,直接说了为后面说到的提供一些依据 1.1 for循环最基本,也是最容易理解的. 1.2 forEach和map用法 ...
- vue的mescroll搜索运用以及各种填坑处理
父组件处理: <template> <div class="wrap"> <!-- 搜索框 --> <div class="se ...
- S3C2440 gpio
WATCHDOG TIMER 原理图 手册 举例 start.S .globl _start _start: /* 关看门狗 */ /* 往WTCON(0x53000000)写0 */ ldr r0, ...
- sql server存储过程解密
解密存储过程: USE [RYTreasureDB] GO /****** Object: StoredProcedure [dbo].[sp__windbi$decrypt] Script Date ...
- dnmp安装
centos7.2.box下载地址 链接: https://pan.baidu.com/s/1ny20PN2x7YuA6dwYA-P0yQ 提取码: wrdk 1 下载centos.box 新建dnm ...
- 【Linux】修改CentOS7启动方式
## 查看当前系统的默认启动方式: systemctl get-default ## 查看如下文件 cat /etc/inittab 可以看到 此文件中提示了如何进行修改默认的启动方式 ## 命令行启 ...
- Linux命令——set 和 unset
参考:Linux set and unset http://www.runoob.com/linux/linux-comm-set.html https://blog.csdn.net/u010003 ...
- <<回想>>
算是一个简单的回忆录,文笔很差,愧对语文老师 突然发现上一篇回忆录,没错就是那个流水账,是去年今天写的... 这是2019年7月的一天,NOI2019刚刚落下帷幕,而小F,则百无聊赖地在高铁站等车 ...
- 使用itchat进行自动微信聊天
import itchat def we_chat(message): #enableCmdQR=2用于linux中显示二维码,hotReload=True退出程序后暂存登录状态 itchat.aut ...