【BZOJ2648】SJY摆棋子(KD-Tree)
【BZOJ2648】SJY摆棋子(KD-Tree)
题面
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
题解
\(KD-Tree\)模板题?
对于分割出来的矩阵,维护矩阵中的点的两维坐标的最大和最小值
这样就可以计算当前点到达这个矩阵的最短距离
这样就可以剪枝啦
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 555555
#define ls (t[x].ch[0])
#define rs (t[x].ch[1])
#define cmin(a,b) (a>b?a=b:a)
#define cmax(a,b) (a<b?a=b:a)
inline int read()
{
RG int x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
int D;
int n,rt,Q;
struct Node{int d[2];}a[MAX];
bool operator<(Node a,Node b){return a.d[D]<b.d[D];}
struct KD_Tree_Node
{
int d[2],mn[2],mx[2];
int ch[2];
}t[MAX<<1];
int ans;
void update(int x,int y)
{
cmin(t[x].mn[0],t[y].mn[0]);cmin(t[x].mn[1],t[y].mn[1]);
cmax(t[x].mx[0],t[y].mx[0]);cmax(t[x].mx[1],t[y].mx[1]);
}
int Build(int l,int r,int nD)
{
int x=(l+r)>>1;D=nD;
nth_element(&a[l],&a[x],&a[r+1]);
t[x].d[0]=t[x].mn[0]=t[x].mx[0]=a[x].d[0];
t[x].d[1]=t[x].mn[1]=t[x].mx[1]=a[x].d[1];
if(l<x)ls=Build(l,x-1,nD^1),update(x,ls);
if(r>x)rs=Build(x+1,r,nD^1),update(x,rs);
return x;
}
int Dist(int nw,int X,int Y)
{
return max(t[nw].mn[0]-X,0)+max(X-t[nw].mx[0],0)+max(t[nw].mn[1]-Y,0)+max(Y-t[nw].mx[1],0);
}
void Query(int x,int xx,int yy)
{
int tmp=abs(t[x].d[0]-xx)+abs(t[x].d[1]-yy),d[2];
d[0]=ls?Dist(ls,xx,yy):2e9;
d[1]=rs?Dist(rs,xx,yy):2e9;
cmin(ans,tmp);tmp=d[0]>=d[1];
if(d[tmp]<ans)Query(t[x].ch[tmp],xx,yy);
if(d[tmp^1]<ans)Query(t[x].ch[tmp^1],xx,yy);
}
int main()
{
n=read();Q=read();
for(int i=1;i<=n;++i)a[i].d[0]=read(),a[i].d[1]=read();
rt=Build(1,n,0);
while(Q--)
{
int opt=read(),x=read(),y=read();
if(opt==1)
{
++n;
t[n].d[0]=t[n].mn[0]=t[n].mx[0]=x;
t[n].d[1]=t[n].mn[1]=t[n].mx[1]=y;
for(int nw=rt,d=0;nw;d^=1)
{
update(nw,n);
int k=t[n].d[d]>=t[nw].d[d];
if(!t[nw].ch[k]){t[nw].ch[k]=n;break;}
nw=t[nw].ch[k];
}
}
else
{
ans=2e9;Query(rt,x,y);
printf("%d\n",ans);
}
}
return 0;
}
上面是不会重建\(KD-Tree\)的代码
洛谷上数据有所加强,这样做会\(TLE\)
所以考虑替罪羊树类似的重构即可
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 555555
#define ls (t[x].ch[0])
#define rs (t[x].ch[1])
#define cmin(a,b) (a>b?a=b:a)
#define cmax(a,b) (a<b?a=b:a)
inline int read()
{
RG int x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
const double alpha=0.75;
int D;
int n,rt,m;
struct Node{int d[2];}a[MAX];
bool operator<(Node a,Node b){return a.d[D]<b.d[D];}
struct KD_Tree_Node
{
int d[2],mn[2],mx[2];
int ch[2],size;
}t[MAX<<1];
int ans;
int Q[MAX<<1],top,tot;
int Num;
int NewNode()
{
if(!top)return ++tot;
return Q[top--];
}
void update(int x,int y)
{
cmin(t[x].mn[0],t[y].mn[0]);cmin(t[x].mn[1],t[y].mn[1]);
cmax(t[x].mx[0],t[y].mx[0]);cmax(t[x].mx[1],t[y].mx[1]);
}
void pushup(int x)
{
t[x].mn[0]=t[x].mx[0]=t[x].d[0];
t[x].mn[1]=t[x].mx[1]=t[x].d[1];
t[x].size=t[ls].size+t[rs].size+1;
if(ls)update(x,ls);if(rs)update(x,rs);
}
int Build(int l,int r,int nD)
{
int mid=(l+r)>>1;D=nD;
nth_element(&a[l],&a[mid],&a[r+1]);
int x=NewNode();
t[x].d[0]=a[mid].d[0];t[x].d[1]=a[mid].d[1];
if(l<mid)ls=Build(l,mid-1,nD^1);else ls=0;
if(r>mid)rs=Build(mid+1,r,nD^1);else rs=0;
pushup(x);return x;
}
int Dist(int nw,int X,int Y)
{
return max(t[nw].mn[0]-X,0)+max(X-t[nw].mx[0],0)+max(t[nw].mn[1]-Y,0)+max(Y-t[nw].mx[1],0);
}
void Query(int x,int xx,int yy)
{
int tmp=abs(t[x].d[0]-xx)+abs(t[x].d[1]-yy),d[2];
d[0]=ls?Dist(ls,xx,yy):2e9;
d[1]=rs?Dist(rs,xx,yy):2e9;
cmin(ans,tmp);tmp=d[0]>=d[1];
if(d[tmp]<ans)Query(t[x].ch[tmp],xx,yy);
if(d[tmp^1]<ans)Query(t[x].ch[tmp^1],xx,yy);
}
void kill(int x){if(ls)kill(ls);a[++Num]=(Node){t[x].d[0],t[x].d[1]};Q[++top]=x;if(rs)kill(rs);}
void check(int &x,int nd)
{
if(t[x].size*alpha<t[ls].size||t[x].size*alpha<t[rs].size)
Num=0,kill(x),x=Build(1,Num,nd);
}
void insert(int &x,Node a,int nd)
{
if(!x){x=NewNode();t[x].d[0]=a.d[0];t[x].d[1]=a.d[1];pushup(x);return;}
if(a.d[nd]>t[x].d[nd])insert(rs,a,nd^1);
else insert(ls,a,nd^1);
pushup(x);check(x,nd);
}
int main()
{
n=read();m=read();
for(int i=1;i<=n;++i)a[i].d[0]=read(),a[i].d[1]=read();
rt=Build(1,n,0);
while(m--)
{
int opt=read(),x=read(),y=read();
if(opt==1)insert(rt,(Node){x,y},0);
else
{
ans=2e9;Query(rt,x,y);
printf("%d\n",ans);
}
}
return 0;
}
【BZOJ2648】SJY摆棋子(KD-Tree)的更多相关文章
- luogu4169 [Violet]天使玩偶/SJY摆棋子 / bzoj2648 SJY摆棋子 k-d tree
k-d tree + 重构的思想,就能卡过luogu和bzoj啦orz #include <algorithm> #include <iostream> #include &l ...
- BZOJ 2648: SJY摆棋子(K-D Tree)
Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 6051 Solved: 2113[Submit][Status][Discuss] Descript ...
- BZOJ2648: SJY摆棋子&&2716: [Violet 3]天使玩偶
BZOJ2648: SJY摆棋子 BZOJ2716: [Violet 3]天使玩偶 BZOJ氪金无极限... 其实这两道是同一题. 附上2648的题面: Description 这天,SJY显得无聊. ...
- [BZOJ2648] SJY摆棋子 kd-tree
2648: SJY摆棋子 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 5421 Solved: 1910[Submit][Status][Disc ...
- Bzoj2648 SJY摆棋子
Time Limit: 20 Sec Memory Limit: 128 MB Submit: 3128 Solved: 1067 Description 这天,SJY显得无聊.在家自己玩.在一个 ...
- bzoj 2648 SJY摆棋子 kd树
题目链接 初始的时候有一些棋子, 然后给两种操作, 一种是往上面放棋子. 另一种是给出一个棋子的位置, 问你离它最近的棋子的曼哈顿距离是多少. 写了指针版本的kd树, 感觉这个版本很好理解. #inc ...
- 2019.01.14 bzoj2648: SJY摆棋子(kd-tree)
传送门 kd−treekd-treekd−tree模板题. 题意简述:支持在平面上插入一个点,求对于一个点的最近点对. 思路:cdqcdqcdq是一种很不错的分治方法 只是好像码量有点窒息 所以我用了 ...
- BZOJ2648 SJY摆棋子(KD-Tree)
板子题. #include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> # ...
- 【kd-tree】bzoj2648 SJY摆棋子
#include<cstdio> #include<cmath> #include<algorithm> using namespace std; #define ...
- [bzoj2648]SJY摆棋子(带插入kd-tree)
解题关键:带插入kdtree模板题. #include<iostream> #include<cstdio> #include<cstring> #include& ...
随机推荐
- (转)EDM邮件制作规范完整版
转载:http://www.maildesign.cn/archives/1380 在我们的日常工作中,经常需要发送邮件和我们的会员沟通.如注册确认.营销推广等.这些由站方发给会员的信件,往往纯文本格 ...
- 02-JVM内存模型:虚拟机栈与本地方法栈
一.虚拟机栈(VM Stack) 1.1)什么是虚拟机栈 虚拟机栈是用于描述java方法执行的内存模型. 每个java方法在执行时,会创建一个“栈帧(stack frame)”,栈帧的结构分为“局部变 ...
- springboot在application.yml中使用了context-path属性导致静态资源法加载,如不能引入vue.js,jquery.js,css等等
在springBoot配置中加入上下文路径 server.context-path=/csdn js,img等静态文件无法加载,出现404的问题 <script type="text/ ...
- 告别加载dll 出错开机加载项大揭秘
提到开机加载(load)项,大家不要以为就是系统启动(run)项.最简单的例子是,杀毒软件或者用户手动删除病毒文件后,注册表中的自动加载信息仍在,登陆系统时就会提示"加载*dll出错,系统找 ...
- (原创)白话KMP算法详解
引子:BF暴力算法 KMP算法知名度相当高,燃鹅其理解难度以及代码实现对于初学数据结构和算法的同学并不友好,经过两天的总结,详细总结KMP算法如下: 初学串的模式匹配时,我们都会接触到,或者说应该能想 ...
- facebook演讲
任何为了更大愿景工作的人,可能会被称为疯子,即使你最终获得成功. 任何为了复杂问题工作的人,都会因为不能全面了解挑战而被指责,即使你不可能事先了解一切. 任何抓住主动权先行一步的人,都会因为步子太快而 ...
- Linux系统查看系统版本命令
以下操作在centos系统上实现,有些方式可能只适用centos/redhat版本系统 uname -a |uname -r查看内核版本信息 [root@node1 ~]# uname -a Linu ...
- IMX6移植htop
top命令查看CPU利用率并不是很方便,因此打算移植htop到imx6上,主要包括以下几个步骤: - 资源下载 htop 下载http://hisham.hm/htop/releases/1.0.1/ ...
- js经典试题之运算符的优先级
js经典试题之运算符 1.假设val已经声明,可定义为任何值.则下面js代码有可能输出的结果为: console.log('Value is ' + (val != '0') ? 'define' : ...
- 20172330 2017-2018-1 《Java程序设计》第八周学习总结
学号 2017-2018-1 <程序设计与数据结构>第八周学习总结 教材学习内容总结 这一章主要是对多态性的学习: 由继承实现多态性 多态性引用能够随时间变化指向不同类型的对象. 对于多态 ...