KDT的坑...

诶最近开坑好频繁啊...感觉没救了TAT

写了几道模板题.....

建树

比如现在有一些二维平面上的点,我们按照维度首先进行一次划分:

比如第一次划分x维,那么我们找到所有点中x坐标为中位数的点,将其作为根,x坐标小于中位数的点划分到左子树,否则划分到右子树。然后递归划分剩余的两侧的点。下一次划分依据为y维,再下一次划分依据为x维。以此类推。

每个节点存储的信息包含为以这个点为根的子树所有的点的矩形的左上角和右下角的坐标。我们在划分结束时更新即可。

那么我们如何查询到一个给定坐标(x,y)曼哈顿距离最近的点呢?

记录全局变量ans,表示目前的最小距离。初值设为INF.

从根节点开始,递归向下查询:首先用当前节点更新答案,随后看左右子树所对应的矩形,若询问点在矩形外,矩形距离的询问点到这个矩形的最近距离,否则为0.

我们优先选择矩形距离比较小的一侧递归向下询问。询问之后,若另一侧的矩形距离不大于当前的最优解,则再询问另一侧。

据神犇说这个过程是最坏O(sqrt(n))的。

考虑插入。

维护一下目前划分的依据是哪一维。

从根开始递归向下插入。

首先用插入点更新当前节点,然后判断一下是应该插入到当前节点的左子树还是右子树,若插入的部分为空,直接插入;否则再递归插入。

2716&&2648 双倍经验....两边一起交+两边一起wa非常爽TAT

 1 #include<bits/stdc++.h>
 2 #define inf 214748364
 3 #define N 1002333
 4 #define rep(i,l,r) for(int i=l;i<=r;i++)
 5 using namespace std;
 6 struct Point{
 7     int mx[2],mn[2],d[2],l,r;
 8     Point(int x=0,int y=0){
 9         l=0,r=0; d[0]=x,d[1]=y;
10     }
11 }p[N],tr[N],T;
12 int ans,flag,root,m,n;
13 bool operator < (Point a,Point b) {
14     return a.d[flag]<b.d[flag];
15 }
16 int dis(Point a,Point b){
17     return abs(a.d[0]-b.d[0])+abs(a.d[1]-b.d[1]);
18 }
19 inline void update(int mid){
20     int l=tr[mid].l,r=tr[mid].r;
21     rep(i,0,1) {
22          if(tr[mid].l)  tr[mid].mn[i]=min(tr[mid].mn[i],tr[l].mn[i]),tr[mid].mx[i]=max(tr[mid].mx[i],tr[l].mx[i]);
23          if(tr[mid].r)  tr[mid].mn[i]=min(tr[mid].mn[i],tr[r].mn[i]),tr[mid].mx[i]=max(tr[mid].mx[i],tr[r].mx[i]);
24     }
25 }
26 int build(int l,int r,int now) {
27     flag=now;
28     int mid=(l+r)>>1;
29     nth_element(p+l,p+mid,p+r+1);
30     tr[mid]=p[mid];
31     rep(i,0,1) tr[mid].mx[i]=tr[mid].mn[i]=tr[mid].d[i];
32     if(l<mid) tr[mid].l=build(l,mid-1,now^1);
33     if(r>mid) tr[mid].r=build(mid+1,r,now^1);
34     update(mid);
35     return mid;
36 }
37 inline void ins(int k,int now) {
38      if(T.d[now]>=tr[k].d[now]) {
39          if(tr[k].r) ins(tr[k].r,now^1); else {
40               tr[k].r=++n; tr[n]=T;
41               rep(i,0,1) tr[n].mx[i]=tr[n].mn[i]=tr[n].d[i];
42          }
43      } else {
44           if(tr[k].l) ins(tr[k].l,now^1); else {
45                tr[k].l=++n; tr[n]=T;
46                rep(i,0,1) tr[n].mx[i]=tr[n].mn[i]=tr[n].d[i];
47           }
48      }
49      update(k);
50 }
51 inline int getdis(int k,Point p) {
52      int ret=0;
53      rep(i,0,1) ret+=max(tr[k].mn[i]-p.d[i],0);
54      rep(i,0,1) ret+=max(p.d[i]-tr[k].mx[i],0);
55      return ret;
56 }
57 void ask(int k,int now) {
58      int d,dl=inf,dr=inf;
59      d=dis(tr[k],T); ans=min(ans,d);
60      if(tr[k].l) dl=getdis(tr[k].l,T);
61      if(tr[k].r) dr=getdis(tr[k].r,T);
62      if(dl<dr) {
63           if(dl<ans) ask(tr[k].l,now^1);
64           if(dr<ans) ask(tr[k].r,now^1);
65      } else {
66           if(dr<ans) ask(tr[k].r,now^1);
67           if(dl<ans) ask(tr[k].l,now^1);
68      }
69 }
70 inline int read(){
71     int x=0,f=1;char ch=getchar();
72     while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
73     while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
74     return x*f;
75 }
76 inline void insert(Point p) {
77      T=p; ins(root,0);
78 }
79 inline int que(Point p){
80      ans=inf; T=p; ask(root,0);
81      return ans;
82 }
83 int main () {
84     register int Q,opt,x,y;
85     scanf("%d%d",&n,&Q);
86     rep(i,1,n) scanf("%d%d",&p[i].d[0],&p[i].d[1]);
87     root=build(1,n,0);
88     while(Q--) {
89          opt=read(); x=read(); y=read();
90          if(opt==1) insert(Point(x,y));else printf("%d\n",que(Point(x,y)));
91     }
92 }

1941:为什么有的省会拿这种奇奇怪怪的东西来考啊喂...

 1 #include<bits/stdc++.h>
 2 #define inf 214748364
 3 #define N 1002333
 4 #define rep(i,l,r) for(int i=l;i<=r;i++)
 5 using namespace std;
 6 struct Point{
 7     int mx[2],mn[2],d[2],l,r;
 8     Point(int x=0,int y=0){
 9         l=0,r=0; d[0]=x,d[1]=y;
10     }
11 }p[N],tr[N],T;
12 int ans,flag,root,m,n,anss;
13 bool operator < (Point a,Point b) {
14     return a.d[flag]<b.d[flag];
15 }
16 int dis(Point a,Point b){
17     return abs(a.d[0]-b.d[0])+abs(a.d[1]-b.d[1]);
18 }
19 inline void update(int mid){
20     int l=tr[mid].l,r=tr[mid].r;
21     rep(i,0,1) {
22          if(tr[mid].l)  tr[mid].mn[i]=min(tr[mid].mn[i],tr[l].mn[i]),tr[mid].mx[i]=max(tr[mid].mx[i],tr[l].mx[i]);
23          if(tr[mid].r)  tr[mid].mn[i]=min(tr[mid].mn[i],tr[r].mn[i]),tr[mid].mx[i]=max(tr[mid].mx[i],tr[r].mx[i]);
24     }
25 }
26 int build(int l,int r,int now) {
27     flag=now;
28     int mid=(l+r)>>1;
29     nth_element(p+l,p+mid,p+r+1);
30     tr[mid]=p[mid];
31     rep(i,0,1) tr[mid].mx[i]=tr[mid].mn[i]=tr[mid].d[i];
32     if(l<mid) tr[mid].l=build(l,mid-1,now^1);
33     if(r>mid) tr[mid].r=build(mid+1,r,now^1);
34     update(mid);
35     return mid;
36 }
37 inline int getdis(int k,Point p) {
38      int ret=0;
39      rep(i,0,1) ret+=max(tr[k].mn[i]-p.d[i],0);
40      rep(i,0,1) ret+=max(p.d[i]-tr[k].mx[i],0);
41      return ret;
42 }
43 void ask(int k,int now) {
44      int d,dl=inf,dr=inf;
45      d=dis(tr[k],T); if(d) ans=min(ans,d);
46      if(tr[k].l) dl=getdis(tr[k].l,T);
47      if(tr[k].r) dr=getdis(tr[k].r,T);
48      if(dl<dr) {
49           if(dl<ans) ask(tr[k].l,now^1);
50           if(dr<ans) ask(tr[k].r,now^1);
51      } else {
52           if(dr<ans) ask(tr[k].r,now^1);
53           if(dl<ans) ask(tr[k].l,now^1);
54      }
55 }
56 inline int que(Point p){
57      ans=inf; T=p; ask(root,0);
58      return ans;
59 }
60 inline int getmax(int k,Point p)  {
61      int ret=0;
62      rep(i,0,1) ret+=max(abs(tr[k].mn[i]-p.d[i]),abs(tr[k].mx[i]-p.d[i]));
63      return ret;
64 }
65 void ask1(int k,int now) {
66      int d,dl=-inf,dr=-inf;
67      d=dis(tr[k],T); ans=max(ans,d);
68      if(tr[k].l) dl=getmax(tr[k].l,T);
69      if(tr[k].r) dr=getmax(tr[k].r,T);
70      if(dl>dr) {
71           if(dl>ans) ask1(tr[k].l,now^1);
72           if(dr>ans) ask1(tr[k].r,now^1);
73      } else {
74           if(dr>ans) ask1(tr[k].r,now^1);
75           if(dl>ans) ask1(tr[k].l,now^1);
76      }
77 }
78 inline int que1(Point p){
79      ans=-inf; T=p; ask1(root,0);
80      return ans;
81 }
82 int main () {
83      scanf("%d",&n);
84      rep(i,1,n) scanf("%d%d",&p[i].d[0],&p[i].d[1]);
85      root=build(1,n,0);
86      int x,y,a,b;
87      anss=inf;
88      rep(i,1,n) {
89           x=p[i].d[0]; y=p[i].d[1];
90           a=que(Point(x,y)); b=que1(Point(x,y));
91           anss=min(anss,b-a);
92      }
93      printf("%d\n",anss);
94 }

时间: 2024-11-03 21:26:40

KDT的坑...的相关文章

移动端点击事件全攻略,有你知道与不知道的各种坑

看标题的时候你可能会想,点击事件有什么好说的,还写一篇攻略?哈哈,如果你这么想,只能说明你too young to simple. 接触过移动端开发的同学可能都会面临点击事件的第一个问题:click事件的300ms延迟响应.不能立即响应给体验造成了很大的困扰,因此解决这个问题就成为了必然. 这个问题的解决方案就是: zepto.js的tap事件.tap事件可以理解为在移动端的click事件,而zepto.js因为几乎完全复制jQuery的api,因此常常被用在h5的开发上用来取代jquery.

[原创] 关于免费VPN我踩过的那些坑

关于免费VPN我踩过的那些坑 因为工作的关系,笔者经常需要用到VPN, 访问国外国网站,你懂的. 我曾经试着自己购买VPS搭建过VPN, 被封了后就没心情再维护了,毕竟直接买VPN比VPS便宜太多.时间一长,也就有了一些经验. 这里总结成表格的形式,分享给大家: [NydusVPN] 知乎推荐的香港VPN, 比直通车好,线路稳定性好,办公游戏适合.注册前7天内可以无条件退款哦.  官方网站  [Astrill] 老牌VPN,但近两年被封底得太厉害,现在已经不太给力了. 注册第一个月能免费使用(付

Linux下GDB调试与对拍(先挖个坑)

应为NOIP要复赛在NOI-Linux下编写程序,所以被迫选择Vim+Gdb(主要是Guide太丑了). 虽然GUIDE的调试功能已经对付大多数的调试,反正学一学GDB的使用也没什么坏处. 1 生成调试信息 要调试C/C++的程序,首先在编译时,我们必须要把调试信息加到可执行文件中.使用编译器(cc/gcc/g++)的 -g 参数可以做到这一点.如: gcc -g hello.c -o hello g++ -g hello.cpp -o hello 如果没有-g,你将看不见程序的函数名.变量名,

Spring Cloud ZooKeeper集成Feign的坑2,服务调用了一次后第二次调用就变成了500,错误:Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is com.n

错误如下: 2017-09-19 15:05:24.659 INFO 9986 --- [ main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.spring[email protected]56528192: startup date [Tue Sep 19 15:05:24 CST 2017]; root of context hierarchy 2017-09-19 15:05:24.858 INFO 9986 --

小心掉入旧墙刷漆的五大“坑”

一些朋友的旧墙刷漆都是由自己一手包办,但墙面重新刷漆有好几个误区需要多加注意的.前期材料的选择.施工的准备以及施工的方法,这都是墙面重新刷漆的重要环节.在这些环节中,一不小心就会掉入误区,现在让我们看看有哪些是需要我们注意的. 第一点:过分在意墙面涂料的品牌 一些朋友认为购买墙面涂料一定要买知名品牌使用才好,当然知名品牌的涂料产品确实有一定的质量保障,但是并不是说我们要一味地追求品牌油漆.其实,市场上许多普通品牌的油漆与知名品牌的质量和粉刷效果相差无几,但是在价格上却有很大的差异.所以家装时,需

angular踩坑之路:初探webpack

之前费了一番力气安装好了angular开发环境,后面的几天都是在angular中文官网上看文档,照着英雄教程一步一步操作,熟悉了angular的一些基本特性,这部分没有遇到什么大问题,还比较顺利.这两天在看官方文档中的Webpack简介,想跟着文档做一遍,了解一下如何用Webpack打包angular项目,结果遇到了一些问题,因为是初学angular和Webpack的小白,这些问题一时难以解决,花费了不少时间,想在这里记录一下. 首先跟着文档将相关的文件都添加到项目中,目录是这样子的: 根据文档

谈谈Vagrant中的那些坑:CentOS

安装了vagrant之后,当然需要将它投入使用.由于计划中的生产环境是 CentOS 7,因此想搭建一个 基于CentOS 7(x86_64)的虚拟开发环境. 最开始的一系列工作,比如在vbox中安装CentOS 7.打包box文件.将box导入vagrant等都不在此一一细述,后面将有专文总结这些过程. 然后坑来了:修改Vagrantfile配置文件欲实现 public_network: config.vm.network "public_network", ip: "19

阿里云磁盘扩容踩坑总结

公司半年前上线一个新的项目,采购了一批阿里云主机,磁盘组成是40G系统盘+100G的数据盘,数据库采用MariaDB Galera Cluster集群部署,由于业务数据量快速增长,导致磁盘存储空间剩余量很少,急需要扩容,先总结整个项目规划中埋下的坑: 1.没有DBA对数据库的容量规划,而前期的运维人员采购时选用100G的SSD云盘: 2.数据库默认使用共享表空间,缺点是删除数据后不释放空间,当数据快速增长后,我们采取了先删除临时表数据的方式来尽量避免暴力扩容,争取在春节期间稳定,删除部分数据后,

跳入linux的第一个坑-因为安装Ubuntu导致的硬盘被误格的恢复.(记TestDisk使用记录)

不看废话,直接跳到操作说明 前几日心血来潮想把家中的旧笔记本换成Linux操作系统,算是在业余生活中正式投入Linux的怀抱.说干就干,发行版选择了Ubuntu,下载了Ubuntu16.04的ISO,下载软碟通,制作成U盘启动.恩,重启电脑,U盘引导,进入安装界面. 恩,安装界面挺炫酷啊,还检测到硬盘中安装的Win8,恩,问我是与其他系统共存还是清除并安装,既然都正式投入怀抱了,肯定只安装Ubuntu啊,Win8,拜拜了,恩,选第二个.下图是网上找的.请注意第二个选项的注意:..算了,我就是看到