题面

在 Byteland 的首都,有一个以围墙包裹的矩形公园,其中以圆形表示游客和树。
公园里有四个入口,分别在四个角落(

1

,

2

,

3

,

4

1, 2, 3, 4

1,2,3,4 分别对应左下、右下、左上、右上)。游客只能从入口进出。
游客可以在他们与公园的两邻边相切的时候进出对应的出口。游客可以在公园里自由活动但不允许与树相交(可以刚好相切)。
你的任务是为每个游客计算,给定他们进入公园的入口,他们可以从哪个入口离开公园。

题解

如果你没有想到并查集,那估计做不出来。

如果想到了并查集,并且精通并查集套路,那这题就是比较灵活的板题了。

两个圈之间存在一条边,边权为两圆距离,表示直径在这个数之内的旅客可以穿过。

再把四壁抽象成点,分别与每个圈存在边权为圆到壁距离的边,表示直径在这个数之内的旅客可以贴着墙过去。

如果把边权小于旅客直径的边都连上,那么旅客能否到达目的地就只取决于四壁之间的连通关系了。简单讨论一下完事。

我们不能每个旅客都现场连边,所以有两种方法,第一种是离线,第二种是预处理,然后在线判断:

预处理出四面墙壁两两连通之前,能通过的最大圆直径,我们可以把边从小到大排序,依次加入,在每对墙壁第一次连通时,记录下当前最大的边权,就是能通过的最大圆直径了。

时间复杂度

O

(

n

2

log

n

)

O(n^2\log n)

O(n2logn) 。

CODE

#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<ctime>
#include<queue>
#include<bitset>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 2005
#define LL long long
#define DB double
#define ENDL putchar('\n')
#define lowbit(x) (-(x) & (x))
#define FI first
#define SE second
#define SI(x) set<x>::iterator
#define BI bitset<MAXN>
#define eps (1e-4)
LL read() {
LL f=1,x=0;char s = getchar();
while(s < '0' || s > '9') {if(s=='-')f = -f;s = getchar();}
while(s >= '0' && s <= '9') {x=x*10+(s-'0');s = getchar();}
return f*x;
}
void putpos(LL x) {
if(!x) return ;
putpos(x/10); putchar('0'+(x%10));
}
void putnum(LL x) {
if(!x) putchar('0');
else if(x < 0) putchar('-'),putpos(-x);
else putpos(x);
}
const int MOD = 1000000007;
int n,m,s,o,k;
int ox[MAXN],oy[MAXN];
DB rr[MAXN];
int U,D,L,R,uy,rx;
DB dis(int x,int y,int a,int b) {
return sqrt((x-a)*1.0*(x-a) + (y-b)*1.0*(y-b));
}
struct it{
int u,v;
DB w;it(){u=v=0;w=0.0;}
it(int U,int V,DB W){u=U;v=V;w=W;}
}e[MAXN*MAXN];
bool cmp(it a,it b) {return a.w < b.w;}
int fa[MAXN];
int findf(int x) {return x==fa[x] ? x:(fa[x]=findf(fa[x]));}
void unionSet(int a,int b) {fa[findf(a)] = findf(b);}
DB le[5][5];
bool OK(int x,int y) {return findf(x) != findf(y);}
int main() {
n = read();m = read();
rx = read();uy = read();
U = n+1;D = n+2;L = n+3;R = n+4;
for(int i = 1;i <= n+4;i ++) fa[i] = i;
int cn = 0;
for(int i = 1;i <= n;i ++) {
ox[i] = read();oy[i] = read();
rr[i] = (DB)read();
for(int j = 1;j < i;j ++) {
e[++ cn] = it(j,i,dis(ox[i],oy[i],ox[j],oy[j])-rr[i]-rr[j]);
}
e[++ cn] = it(i,U,(DB)uy-oy[i]-rr[i]);
e[++ cn] = it(i,D,(DB)oy[i]-rr[i]);
e[++ cn] = it(i,L,(DB)ox[i]-rr[i]);
e[++ cn] = it(i,R,(DB)rx-ox[i]-rr[i]);
}
sort(e + 1,e + 1 + cn,cmp);
for(int i = 1;i <= 4;i ++) {
for(int j = 1;j <= 4;j ++) {
le[i][j] = -1.0;
}
}
for(int i = 1;i <= cn;i ++) {
s = e[i].u,o = e[i].v;
DB nw = e[i].w;
if(OK(D,U) && OK(D,L) && OK(D,R)) le[1][2] = le[2][1] = nw;
if(OK(L,U) && OK(L,D) && OK(L,R)) le[1][4] = le[4][1] = nw;
if(OK(L,R) && OK(U,D) && OK(U,R) && OK(L,D)) le[1][3] = le[3][1] = nw;
if(OK(L,U) && OK(L,R) && OK(D,U) && OK(D,R)) le[2][4] = le[4][2] = nw;
if(OK(R,U) && OK(R,L) && OK(R,D)) le[2][3] = le[3][2] = nw;
if(OK(U,L) && OK(U,D) && OK(U,R)) le[3][4] = le[4][3] = nw;
if(findf(s) != findf(o)) {
unionSet(s,o);
}
}
for(int i = 1;i <= m;i ++) {
k = read()*2; s = read();
for(int j = 1;j <= 4;j ++) {
if(le[s][j]+eps >= (DB)k || j == s) {
putchar('0'+j);
}
}ENDL;
}
return 0;
}

P4675 [BalticOI 2016 day1]Park (并查集)的更多相关文章

  1. BZOJ 4551 HEOI 2016 树 (并查集)

    思路: 考虑时光倒流 这不就是并查集裸题了-----. //By SiriusRen #include <cstdio> #include <cstring> #include ...

  2. UVALive 6889 City Park 并查集

    City Park 题目连接: http://acm.hust.edu.cn/vjudge/contest/view.action?cid=122283#problem/F Description P ...

  3. 并查集 - UVALive 6889 City Park

    City Park Problem's Link: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=129725 Mean: 在 ...

  4. Codeforces Gym 101194G Pandaria (2016 ACM-ICPC EC-Final G题, 并查集 + 线段树合并)

    题目链接  2016 ACM-ICPC EC-Final Problem G 题意  给定一个无向图.每个点有一种颜色. 现在给定$q$个询问,每次询问$x$和$w$,求所有能通过边权值不超过$w$的 ...

  5. HDU 5923 Prediction(2016 CCPC东北地区大学生程序设计竞赛 Problem B,并查集)

    题目链接  2016 CCPC东北地区大学生程序设计竞赛 B题 题意  给定一个无向图和一棵树,树上的每个结点对应无向图中的一条边,现在给出$q$个询问, 每次选定树中的一个点集,然后真正被选上的是这 ...

  6. HDU 1116 || POJ 1386 || ZOJ 2016 Play on Words (欧拉回路+并查集)

    题目链接 题意 : 有很多门,每个门上有很多磁盘,每个盘上一个单词,必须重新排列磁盘使得每个单词的第一个字母与前一个单词的最后一个字母相同.给你一组单词问能不能排成上述形式. 思路 :把每个单词看成有 ...

  7. 【 NOIP2015 DAY1 T2 信息传递】带权并查集

    题目描述 有n个同学(编号为1到n)正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其中,编号为i的同学的信息传递对象是编号为Ti同学. 游戏开始时,每人都只知道自己的生日.之后每一 ...

  8. 数据结构(并查集||树链剖分):HEOI 2016 tree

    [注意事项] 为了体现增强版,题目限制和数据范围有所增强: 时间限制:1.5s 内存限制:128MB 对于15% 的数据,1<=N,Q<=1000. 对于35% 的数据,1<=N,Q ...

  9. Stanford Local 2016 E "Election of Evil"(搜索(正解)或并查集(划掉))

    传送门 题意: 给出集合U,V,集合U有n个元素,集合V有m个元素: 有 m 个操作,mi : s1 s2 有一条s1指向s2的边(s1,s2可能属于第三个集合,暂且称之为K集合): 指向边具有传递性 ...

随机推荐

  1. 【高并发】通过ThreadPoolExecutor类的源码深度解析线程池执行任务的核心流程

    核心逻辑概述 ThreadPoolExecutor是Java线程池中最核心的类之一,它能够保证线程池按照正常的业务逻辑执行任务,并通过原子方式更新线程池每个阶段的状态. ThreadPoolExecu ...

  2. rhel安装vmtools

    第一步,vmware登录虚拟机,菜单栏找到"虚拟机"--"安装TOOLS" //如果打开虚拟机的光驱后没有文件.那么重复以上操作. 第二步,拷贝压缩文件到桌面: ...

  3. 全新升级的AOP框架Dora.Interception[6]: 框架设计和实现原理

    本系列前面的五篇文章主要介绍Dora.Interception(github地址,觉得不错不妨给一颗星)的编程模式以及对它的扩展定制,现在我们来聊聊它的设计和实现原理.(拙著<ASP.NET C ...

  4. Python简单实现自动评论、自动点赞、自动关注脚本

    一些哔哔: 今天的这个脚本,是一个别人发的外包,交互界面的代码就不在这里说了,但是可以分享下自动评论.自动点赞.自动关注.采集评论和视频的数据是如何实现的 开发环境 python 3.8 运行代码py ...

  5. 使用Scrcpy投屏

    下载Scrcpy: https://wwt.lanzouw.com/iAzie07bz85c官网地址: https://github.com/Genymobile/scrcpy 记录当前下载位置: 手 ...

  6. 链表设计与Java实现,手写LinkedList这也太清楚了吧!!!

    链表设计与实现 在谈链表之前,我们先谈谈我们平常编程会遇到的很常见的一个问题.如果在编程的时候,某个变量在后续编程中仍需使用,我们可以用一个局部变量来保存该值,除此之外一个更加常用的方法就是使用容器了 ...

  7. 【跟着大佬学JavaScript】之节流

    前言 js的典型的场景 监听页面的scroll事件 拖拽事件 监听鼠标的 mousemove 事件 ... 这些事件会频繁触发会影响性能,如果使用节流,降低频次,保留了用户体验,又提升了执行速度,节省 ...

  8. ubuntu20.04安装测试uhttpd

    uhttpd是openwrt上运行一个高效小型Http服务,支持cgi, lua等特性.可以直接通过snap方式安装,如果是16.04,18.04或者20.04,snap已经默认安装了:如果是其它版本 ...

  9. APISpace 月出月落和月相API接口 免费好用

     月出和月落的位置,正如地球围绕太阳变化时产生的日出和日落一样,但是也和月相有关.一天中月亮升起的时间取决于它的月相.当你记得月相取决于太阳,月亮和地球的相对位置应该是明显的.月相是指从地球上看月球直 ...

  10. 多校B层冲刺NOIP20211110 字符配对游戏

    原题 问题描述 操场边,运动会没有项目的同学也没闲着,经过几天的研究,他们发明了一个很有意思的字符串配对游戏,两位同学准备两张白纸,第一个同学在纸上写一个整数N和一个由小写字母组成的字符串S,将S重复 ...