题面

在 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. conda cheat sheet可直接百度这个名字

  2. 互联网公司实行目标管理(OKR)五点原则和基础

    下面从公司文化.组织架构.管理者.落地执行和区别绩效考核五个方面,讲述了如何在公司落地目标管理(OKR),这些是实施OKR的基础,也是原则,虽然写得比较简单,其实是我过去两年多不断观察.实践和摸索的总 ...

  3. C++ 炼气期之数据是主角

    1. 前言 数据在程序中的重要性,怎么强调都不为过,程序的本质就是通过提供数据处理逻辑,把数据从一种状态变成另一种状态的过程.处理逻辑一定是有针对性的,针对的是数据本身的特性. 只有了解了数据本身的内 ...

  4. SAP 实例 9 Text output

    REPORT demo_show_text. CLASS demo DEFINITION. PUBLIC SECTION. CLASS-METHODS main. ENDCLASS. CLASS de ...

  5. SAP 文件操作类 CL_GUI_FRONTEND_SERVICES

    1 .文件下载. DATA: l_filename TYPE string, "file name l_path TYPE string, "file path l_fullpat ...

  6. SE37 绕过权限检查 ALINK_CALL_TRANSACTION

  7. 分布式机器学习:同步并行SGD算法的实现与复杂度分析(PySpark)

    1 分布式机器学习概述 大规模机器学习训练常面临计算量大.训练数据大(单机存不下).模型规模大的问题,对此分布式机器学习是一个很好的解决方案. 1)对于计算量大的问题,分布式多机并行运算可以基本解决. ...

  8. 全新升级的AOP框架Dora.Interception[6]: 实现任意的拦截器注册方式

    Dora.Interception提供了两种拦截器注册方式,一种是利用标注在目标类型.属性和方法上的InterceptorAttribute特性,另一种采用基于目标方法或者属性的调用表达式.通过提供的 ...

  9. linux web漏洞扫描arachni

    1. 下载arachni https://www.arachni-scanner.com/download/下载Linux x86 64bit 2. 上次解压直接使用 tar xzf arachni- ...

  10. 分享一款IDEA主题,很奈斯

    主题名称:Dark Purple Theme: 更换主题:在Setting中设置更换