HDU 5809 Ants(KD树+并查集)
【题目链接】 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树+并查集)的更多相关文章
- HDU 1512 左偏树+并查集
思路: 左偏树里面掺了一些并查集的应用 这里放一份左偏树的代码模板 重点就是merge函数了-- int merge(int k1,int k2){ if(!k1||!k2)return k1+k2; ...
- [WC2005]双面棋盘(线段树+并查集)
线段树+并查集维护连通性. 好像 \(700ms\) 的时限把我的常数超级大的做法卡掉了, 必须要开 \(O_2\) 才行. 对于线段树的每一个结点都开左边的并查集,右边的并查集,然后合并. \(Co ...
- 洛谷 - P1552 - 派遣 - 左偏树 - 并查集
首先把这个树建出来,然后每一次操作,只能选中一棵子树.对于树根,他的领导力水平是确定的,然后他更新答案的情况就是把他子树内薪水最少的若干个弄出来. 问题在于怎么知道一棵子树内薪水最少的若干个分别是谁. ...
- 洛谷 - P3377 - 【模板】左偏树(可并堆) - 左偏树 - 并查集
https://www.luogu.org/problemnew/show/P3377 左偏树+并查集 左偏树维护两个可合并的堆,并查集维护两个堆元素合并后可以找到正确的树根. 关键点在于删除一个堆的 ...
- 2022.02.27 CF811E Vladik and Entertaining Flags(线段树+并查集)
2022.02.27 CF811E Vladik and Entertaining Flags(线段树+并查集) https://www.luogu.com.cn/problem/CF811E Ste ...
- HDU 1512 Monkey King(左偏树+并查集)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=1512 [题目大意] 现在有 一群互不认识的猴子,每个猴子有一个能力值,每次选择两个猴子,挑出他们所 ...
- hdu 3172 Virtual Friends(并查集,字典树)
题意:人与人交友构成关系网,两个人交友,相当于两个朋友圈的合并,问每个出两人,他们目前所在的关系网中的人数. 分析:用并查集,其实就是求每个集合当前的人数.对于人名的处理用到了字典树. 注意:1.题目 ...
- HDU 1512 Monkey King (左偏树+并查集)
题意:在一个森林里住着N(N<=10000)只猴子.在一开始,他们是互不认识的.但是随着时间的推移,猴子们少不了争斗,但那只会发生在互不认识 (认识具有传递性)的两只猴子之间.争斗时,两只猴子都 ...
- HDU - 1272 小希的迷宫 并查集判断无向环及连通问题 树的性质
小希的迷宫 上次Gardon的迷宫城堡小希玩了很久(见Problem B),现在她也想设计一个迷宫让Gardon来走.但是她设计迷宫的思路不一样,首先她认为所有的通道都应该是双向连通的,就是说如果有一 ...
随机推荐
- jquery1.11 操作checkbox:全选、取消全选、获取选择元素、获取取消选择元素(总结)
jquery1.11.1版本完成对checkbox的操作 1. 使用属性prop设置选中状态 2.使用:checked和:not(:checked)获取选中的元素 源码: <!DOCTYPE h ...
- Android之修改部分字体颜色
#01# 方法一: TextView textView = (TextView) view.findViewById(R.id.text); SpannableString ss = new Span ...
- AutoCompleteTextView 和 TextWatcher 详解
TextWatcher 监测Edittext内容的变化------------------------------------------------------------------------- ...
- PHP5的类与对象
类是一个由变量和方法组成的独立程序块或功能模块. 人类: 口,脚,身高,体重,姓名,肤色等 (变量) 说话,行走等(方法) 丁三石,马化树,张夕阳(具体对象) 类的定义和对象的创建
- MUD教程--巫师入门教程3
1. 指令格式为:edit <档名>,只加文件名,默认为当前目录,加here,表示编辑你当前所处的房间, 回车后即进入线上编辑系统. 2. 如果这是一个已经有的档案,你可以使用 z 或 Z ...
- 论山寨手机与Android联姻的技术基础 【序】
山寨手机的兴起,离不开 MTK(联发科).MTK为手机制造提供了一揽子解决方案,其中既包括硬件,也包括软件.软件方面最重要的,是操作系统.MTK方案的软件的稳定性非常高,一方面是因为其硬件系统变化不大 ...
- 剑指offer35 第一个只出现一次的字符
class Solution { public: int FirstNotRepeatingChar(string str) { if(!str.size()) ; ]={}; ;i<str.s ...
- Java压缩技术的学习
由于工作的需要,经常要手动去打上线安装包,为了方便,自己写程序去帮助打包.使用过Unix或者Linux的人都基本上都用过tar打包以及gzip压缩,但在Windows下使用得最多的压缩还是RAR和Zi ...
- Sql Service存储过程分页
一起是用oracle数据库..感觉oracle数据库强大.查询速度是杠杠的.换了家公司用的是SQL SERVICE.以前用了1年现在捡回以前的记忆.动手写了动态SQL过存储过程分页.感觉和oracle ...
- JS 把 Wed Jul 15 2015 00:00:00 GMT+0800 转换成2015-07-15
function strlen(str) { var len = 0; for (var i = 0; i < str.length; i++) { var c = str.charCodeAt ...