题目大意:维护一个二维平面,平面上初始有 N 个点,支持两种操作:平面加点、查询距离某个指定点的最小哈密顿距离。

题解:学习到了 kd-tree 数据结构。

kd-tree 类似于平衡树,即:每个节点都维护了一个点坐标的信息和一个矩形区间的边界,与线段树的 leafy tree 性质不同。不过,由于 kd-tree 不涉及旋转以及维护的矩形区域的分割特征,可以使用 pushup 操作进行上传边界信息。kd-tree 的查询优化算法核心思想基于估价函数的设计,估价函数一般是某一个区域的最优解,即:若某个区域的最优解都不能对答案产生影响,那么直接忽略这块区域即可,这样就可以使得时间复杂度降低,从而达到优化的目的。时间复杂度为 \(O(\sqrt(n))\),目前不会证明。。

update at 2019.3.17

代码如下

#include <bits/stdc++.h>
using namespace std;
const int maxn=3e5+10;
const int inf=0x3f3f3f3f;
const double alpha=0.75; inline int read(){
int x=0,f=1;char ch;
do{ch=getchar();if(ch=='-')f=-1;}while(!isdigit(ch));
do{x=x*10+ch-'0';ch=getchar();}while(isdigit(ch));
return f*x;
} int n,m;
struct node{
#define ls(x) t[x].ch[0]
#define rs(x) t[x].ch[1]
int p[2],x[2],y[2],ch[2],size;
}t[maxn<<1];
int root,d,ans,id[maxn],tot;
inline bool cmp(int x,int y){return t[x].p[d]<t[y].p[d];}
inline int getdis(int o,int x,int y){
return max(t[o].x[0]-x,0)+max(x-t[o].x[1],0)+max(t[o].y[0]-y,0)+max(y-t[o].y[1],0);
}
inline void pushup(int o){
t[o].x[0]=min(min(t[ls(o)].x[0],t[rs(o)].x[0]),t[o].p[0]);
t[o].x[1]=max(max(t[ls(o)].x[1],t[rs(o)].x[1]),t[o].p[0]);
t[o].y[0]=min(min(t[ls(o)].y[0],t[rs(o)].y[0]),t[o].p[1]);
t[o].y[1]=max(max(t[ls(o)].y[1],t[rs(o)].y[1]),t[o].p[1]);
t[o].size=t[ls(o)].size+t[rs(o)].size+1;
}
int build(int l,int r,int now){
if(l>r)return 0;
int mid=l+r>>1;
d=now,nth_element(id+l,id+mid,id+r+1,cmp);
ls(id[mid])=build(l,mid-1,now^1),rs(id[mid])=build(mid+1,r,now^1);
return pushup(id[mid]),id[mid];
}
inline bool isbad(int o){return (double)max(t[ls(o)].size,t[rs(o)].size)>alpha*t[o].size;}
void dfs(int o){if(o)dfs(ls(o)),id[++tot]=o,dfs(rs(o));}
void insert(int &o,int p[2],int now){
if(!o){
o=++n,t[o].p[0]=p[0],t[o].p[1]=p[1],pushup(o);
return;
}
else if(t[o].p[now]<=p[now])insert(rs(o),p,now^1);
else insert(ls(o),p,now^1);
pushup(o);
if(isbad(o))tot=0,dfs(o),o=build(1,tot,now);
}
void query(int o,int x,int y){
int dn=abs(x-t[o].p[0])+abs(y-t[o].p[1]),dl,dr;
ans=min(ans,dn);
dl=ls(o)?getdis(ls(o),x,y):inf;
dr=rs(o)?getdis(rs(o),x,y):inf;
if(dl<dr){
if(dl<ans)query(ls(o),x,y);
if(dr<ans)query(rs(o),x,y);
}else{
if(dr<ans)query(rs(o),x,y);
if(dl<ans)query(ls(o),x,y);
}
} void read_and_parse(){
t[0].x[0]=t[0].y[0]=inf,t[0].x[1]=t[0].y[1]=-inf;
n=read(),m=read();
for(int i=1;i<=n;i++)t[i].p[0]=read(),t[i].p[1]=read(),id[++tot]=i;
root=build(1,n,0);
} void solve(){
int p[2];
while(m--){
int opt=read(),x=read(),y=read();
if(opt==1)p[0]=x,p[1]=y,insert(root,p,0);
else ans=inf,query(root,x,y),printf("%d\n",ans);
}
} int main(){
read_and_parse();
solve();
return 0;
}

最新文章

  1. 【Java EE 学习 17 下】【数据库导出到Excel】【多条件查询方法】
  2. 0代码隐藏GroupedTableView上边多余的间隔
  3. apache本地网址配置
  4. Can&#39;t connect to local MySQL server through socket
  5. Spring Data Elasticsearch
  6. WebService-调用第三方提供的webService服务
  7. 我的第一个html计算器
  8. 灵光一闪-VS设计界面能访问到private修饰的各种控件
  9. Python open()
  10. OCP 11G 实验环境安装文档 ( RedHat5.5 + Oracle11g )
  11. ubuntu 使用sudo apt-get update 出现 被配置多次导致无法升级错误解决方法
  12. deeplearning.ai 神经网络和深度学习 week2 神经网络基础 听课笔记
  13. 如何用sysbench做好IO性能测试
  14. 【憩园】C#并发编程之概述
  15. ACM-ICPC 2018 沈阳赛区网络预赛 I. Lattice&#39;s basics in digital electronics 阅读题加模拟题
  16. 推荐:全新Java开发思维导图
  17. MFC框架之线程局部存储
  18. 课程一(Neural Networks and Deep Learning),第一周(Introduction to Deep Learning)—— 2、10个测验题
  19. RabbitMQ路由类型
  20. oracle对三个列求sum

热门文章

  1. 【下一代核心技术DevOps】:(六)Rancher集中存储及相关应用
  2. Visual studio2015 编译时提示“GenerateResource”任务意外失败。
  3. SCRUM 12.23
  4. 20135337——Linux内核分析:第十七章 模块与设备
  5. 同步手绘板——json
  6. 软件工程-pair work[附加题]
  7. 个人作业 - Week3 - 案例分析
  8. maven上传本地jar包到私服
  9. shell脚本--权限分配
  10. Ehcache配置参数示例