【题目链接】 http://acm.hdu.edu.cn/showproblem.php?pid=5809

【题目大意】

  给出一些蚂蚁和他们的巢穴,一开始他们会在自己的巢穴(以二维坐标形式给出),之后每一个时刻会向距离自己最近的巢穴移动,当两只蚂蚁相向而行的时候,我们可以认为他们相遇了,现在有q个询问,每个询问需要让你判断蚂蚁x和y是否会相遇。

【题解】

  我们可以发现对于一只蚂蚁来说,他最后肯定会陷入一个二元环中来回走动,那么我们只要判断是否最后两只蚂蚁会出现在同一个二元环中,那么就可以判断他们是否可以相遇。

  首先对于所有点构建KD树,对于每个点计算离它最近的点,将两个点加入同一个集合,最后判断询问两点是否属于同一个集合即可,集合的合并和判断可以用并查集实现。

【代码】

#include <cstdio>
#include <algorithm>
const int N=400010;
int n,i,id[N],root,cmp_d;
typedef long long LL;
const LL INF=0x3f3f3f3f3f3f3f3fLL;
struct node{
int d[2],l,r,Max[2],Min[2],val,sum,f,id;
bool operator<(const node& B){return d[0]<B.d[0]||(d[0]==B.d[0]&&d[1]<B.d[1]);}
}t[N];
inline bool cmp(const node&a,const node&b){return a.d[cmp_d]<b.d[cmp_d];}
inline void umax(int&a,int b){if(a<b)a=b;}
inline void umin(int&a,int b){if(a>b)a=b;}
inline void up(int x){
if(t[x].l){
umax(t[x].Max[0],t[t[x].l].Max[0]);
umin(t[x].Min[0],t[t[x].l].Min[0]);
umax(t[x].Max[1],t[t[x].l].Max[1]);
umin(t[x].Min[1],t[t[x].l].Min[1]);
}
if(t[x].r){
umax(t[x].Max[0],t[t[x].r].Max[0]);
umin(t[x].Min[0],t[t[x].r].Min[0]);
umax(t[x].Max[1],t[t[x].r].Max[1]);
umin(t[x].Min[1],t[t[x].r].Min[1]);
}
}
int build(int l,int r,int D,int f){
int mid=(l+r)>>1;
cmp_d=D,std::nth_element(t+l+1,t+mid+1,t+r+1,cmp);
id[t[mid].f]=mid;
t[mid].f=f;
t[mid].Max[0]=t[mid].Min[0]=t[mid].d[0];
t[mid].Max[1]=t[mid].Min[1]=t[mid].d[1];
t[mid].val=t[mid].sum=0;
if(l!=mid)t[mid].l=build(l,mid-1,!D,mid);else t[mid].l=0;
if(r!=mid)t[mid].r=build(mid+1,r,!D,mid);else t[mid].r=0;
return up(mid),mid;
}
inline LL sqr(int x){return (LL)x*x;}
LL ans; node ansP;
LL ans2; node ansP2;
int px,py;
inline LL dist(int p1){
LL dis=0;
if(px<t[p1].Min[0])dis+=sqr(t[p1].Min[0]-px);
if(px>t[p1].Max[0])dis+=sqr(px-t[p1].Max[0]);
if(py<t[p1].Min[1])dis+=sqr(t[p1].Min[1]-py);
if(py>t[p1].Max[1])dis+=sqr(py-t[p1].Max[1]);
return dis;
}
void ask(int x){
LL dl,dr,d0=sqr(t[x].d[0]-px)+sqr(t[x].d[1]-py);
if(d0<ans||(d0==ans&&t[x]<ansP))ans2=ans,ansP2=ansP,ans=d0,ansP=t[x];
else if(d0<ans2||(d0==ans2&&t[x]<ansP2))ans2=d0,ansP2=t[x];
dl=t[x].l?dist(t[x].l):INF;
dr=t[x].r?dist(t[x].r):INF;
if(dl<dr){
if(dl<=ans2)ask(t[x].l);
if(dr<=ans2)ask(t[x].r);
}else{
if(dr<=ans2)ask(t[x].r);
if(dl<=ans2)ask(t[x].l);
}
}
int getP(int root){
ans=ans2=INF; ask(root); return ansP2.id;
}
int T,x,y,Cas=1,q,f[N];
int sf(int x){return f[x]==x?f[x]:f[x]=sf(f[x]);}
int main(){
scanf("%d",&T);
while(T--){
printf("Case #%d:\n",Cas++);
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++){
scanf("%d%d",&x,&y);
t[i].d[0]=x,t[i].d[1]=y,t[i].id=i;
}root=build(1,n,0,0);
for(int i=1;i<=n;i++)f[i]=i;
for(int i=1;i<=n;i++){
px=t[i].d[0],py=t[i].d[1];
x=t[i].id,y=getP(root);
f[sf(x)]=sf(y);
}
while(q--){
scanf("%d%d",&x,&y);
puts(sf(x)==sf(y)?"YES":"NO");
}
}return 0;
}

HDU 5809 Ants(KD树+并查集)的更多相关文章

  1. HDU 1512 左偏树+并查集

    思路: 左偏树里面掺了一些并查集的应用 这里放一份左偏树的代码模板 重点就是merge函数了-- int merge(int k1,int k2){ if(!k1||!k2)return k1+k2; ...

  2. [WC2005]双面棋盘(线段树+并查集)

    线段树+并查集维护连通性. 好像 \(700ms\) 的时限把我的常数超级大的做法卡掉了, 必须要开 \(O_2\) 才行. 对于线段树的每一个结点都开左边的并查集,右边的并查集,然后合并. \(Co ...

  3. 洛谷 - P1552 - 派遣 - 左偏树 - 并查集

    首先把这个树建出来,然后每一次操作,只能选中一棵子树.对于树根,他的领导力水平是确定的,然后他更新答案的情况就是把他子树内薪水最少的若干个弄出来. 问题在于怎么知道一棵子树内薪水最少的若干个分别是谁. ...

  4. 洛谷 - P3377 - 【模板】左偏树(可并堆) - 左偏树 - 并查集

    https://www.luogu.org/problemnew/show/P3377 左偏树+并查集 左偏树维护两个可合并的堆,并查集维护两个堆元素合并后可以找到正确的树根. 关键点在于删除一个堆的 ...

  5. 2022.02.27 CF811E Vladik and Entertaining Flags(线段树+并查集)

    2022.02.27 CF811E Vladik and Entertaining Flags(线段树+并查集) https://www.luogu.com.cn/problem/CF811E Ste ...

  6. HDU 1512 Monkey King(左偏树+并查集)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=1512 [题目大意] 现在有 一群互不认识的猴子,每个猴子有一个能力值,每次选择两个猴子,挑出他们所 ...

  7. hdu 3172 Virtual Friends(并查集,字典树)

    题意:人与人交友构成关系网,两个人交友,相当于两个朋友圈的合并,问每个出两人,他们目前所在的关系网中的人数. 分析:用并查集,其实就是求每个集合当前的人数.对于人名的处理用到了字典树. 注意:1.题目 ...

  8. HDU 1512 Monkey King (左偏树+并查集)

    题意:在一个森林里住着N(N<=10000)只猴子.在一开始,他们是互不认识的.但是随着时间的推移,猴子们少不了争斗,但那只会发生在互不认识 (认识具有传递性)的两只猴子之间.争斗时,两只猴子都 ...

  9. HDU - 1272 小希的迷宫 并查集判断无向环及连通问题 树的性质

    小希的迷宫 上次Gardon的迷宫城堡小希玩了很久(见Problem B),现在她也想设计一个迷宫让Gardon来走.但是她设计迷宫的思路不一样,首先她认为所有的通道都应该是双向连通的,就是说如果有一 ...

随机推荐

  1. 仿淘宝TAB切换搜索框

    <div class="search"> <div id="searchBox"> <ul class="tab-bar ...

  2. mysql explain 命令简解

    参考官方文档地址: http://dev.mysql.com/doc/refman/5.7/en/explain.html 为什么用explain . 如果你的页面返回结果很慢,你就需要使用expla ...

  3. jupyter巨好玩-调试代码自动变文档

    有时候,我们写python程序,总是会出现各种错误,当酒过三巡,菜过五味,所有问题都解决了之后,我们就想把犯过的错误总结一下,以便日后查询.这时候问题来了,难道要一一重现一下? jupyter来了!一 ...

  4. jchat:linux聊天程序2:MySQL

    该软件使用的数据库为MySQL,因为它免费.开源,在linux下几乎就是最好的选择. 首先要在mysql中root用户新建数据库并赋权给本用户: create database jchat; gran ...

  5. ab压力测试报错: apr_socket_recv: Connection reset by peer (104)

    使用ab对网站进行压力测试,开始设置并发500,可以正常使用,当设置并发为1000,则报错: apr_socket_recv: Connection reset by peer (104) 改服务端a ...

  6. 很详细、很移动的Linux makefile教程:介绍,总述,书写规则,书写命令,使用变量,使用条件推断,使用函数,Make 的运行,隐含规则 使用make更新函数库文件 后序

    很详细.很移动的Linux makefile 教程 内容如下: Makefile 介绍 Makefile 总述 书写规则 书写命令 使用变量 使用条件推断 使用函数 make 的运行 隐含规则 使用m ...

  7. wx

    wx The classes in this module are the most commonly used classes for wxPython, which is why they hav ...

  8. 不同版本的 IIS 中使用 ASP.NET MVC(C#)【转】

    由微软 ASP.NET 团队|2008 年 8 月 19 日 推特 在本教程中,您将学习在不同版本的 Internet Information Services 中如何使用 ASP.NET MVC 和 ...

  9. HTTP状态码(HTTP Status Code)【转】

    HTTP状态码(HTTP Status Code) 一些常见的状态码为: 200 - 服务器成功返回网页 404 - 请求的网页不存在 503 - 服务不可用 所有状态解释:点击查看 1xx(临时响应 ...

  10. Asp.Net之三层架构

    三层架构之理论: 通常意义上讲的三层架构就是将整个项目应用划分为:表现层(UI),业务逻辑层(BLL),数据访问层(DAL).与传统的二层架构的区别在于在用户界面(UI)和数据库服务器之间,添加中间层 ...