P4675 [BalticOI 2016 day1]Park (并查集)
题面
在 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 (并查集)的更多相关文章
- BZOJ 4551 HEOI 2016 树 (并查集)
思路: 考虑时光倒流 这不就是并查集裸题了-----. //By SiriusRen #include <cstdio> #include <cstring> #include ...
- UVALive 6889 City Park 并查集
City Park 题目连接: http://acm.hust.edu.cn/vjudge/contest/view.action?cid=122283#problem/F Description P ...
- 并查集 - UVALive 6889 City Park
City Park Problem's Link: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=129725 Mean: 在 ...
- Codeforces Gym 101194G Pandaria (2016 ACM-ICPC EC-Final G题, 并查集 + 线段树合并)
题目链接 2016 ACM-ICPC EC-Final Problem G 题意 给定一个无向图.每个点有一种颜色. 现在给定$q$个询问,每次询问$x$和$w$,求所有能通过边权值不超过$w$的 ...
- HDU 5923 Prediction(2016 CCPC东北地区大学生程序设计竞赛 Problem B,并查集)
题目链接 2016 CCPC东北地区大学生程序设计竞赛 B题 题意 给定一个无向图和一棵树,树上的每个结点对应无向图中的一条边,现在给出$q$个询问, 每次选定树中的一个点集,然后真正被选上的是这 ...
- HDU 1116 || POJ 1386 || ZOJ 2016 Play on Words (欧拉回路+并查集)
题目链接 题意 : 有很多门,每个门上有很多磁盘,每个盘上一个单词,必须重新排列磁盘使得每个单词的第一个字母与前一个单词的最后一个字母相同.给你一组单词问能不能排成上述形式. 思路 :把每个单词看成有 ...
- 【 NOIP2015 DAY1 T2 信息传递】带权并查集
题目描述 有n个同学(编号为1到n)正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其中,编号为i的同学的信息传递对象是编号为Ti同学. 游戏开始时,每人都只知道自己的生日.之后每一 ...
- 数据结构(并查集||树链剖分):HEOI 2016 tree
[注意事项] 为了体现增强版,题目限制和数据范围有所增强: 时间限制:1.5s 内存限制:128MB 对于15% 的数据,1<=N,Q<=1000. 对于35% 的数据,1<=N,Q ...
- Stanford Local 2016 E "Election of Evil"(搜索(正解)或并查集(划掉))
传送门 题意: 给出集合U,V,集合U有n个元素,集合V有m个元素: 有 m 个操作,mi : s1 s2 有一条s1指向s2的边(s1,s2可能属于第三个集合,暂且称之为K集合): 指向边具有传递性 ...
随机推荐
- DDos、CC攻击与防御
DDoS介绍 DDoS是英文Distributed Denial of Service的缩写,意即"分布式拒绝服务",那么什么又是拒绝服务(Denial of Service)呢? ...
- 嵌入式中 动态阿拉伯语字符串 转换 LCD显示字符串【感谢建国雄心】
本文参考CSDBN:建国雄心 的博客,这里找不到该帖子,放一个类似的仅供参考https://blog.csdn.net/qiaojiongzeng6321/article/details/748572 ...
- Turtle绘图——python简单上手小案例
Turtle绘图 Turtle模块提供了在二维平面上移动的环境. Turtle可以实现位置.航向和各种可能的状态和动作. import turtle as tu roo = tu.Turtle() # ...
- 在mybatis中使用sum函数返回对象为Null
首先大家看一下我的XML中的SQL .DAO 和实体对象 XML DAO PO 乍一看 没毛病. 但是在Mybatis中使用sum函数,如果返回值是0(就是你在Navicat中运行的的sql正常,结 ...
- 一文读懂数仓中的pg_stat
摘要:GaussDB(DWS)在SQL执行过程中,会记录表增删改查相关的运行时统计信息,并在事务提交或回滚后记录到共享的内存中.这些信息可以通过 "pg_stat_all_tables视图& ...
- 使用vs2022编译assimp,并基于OpenGL加载模型
Assimp :全称为Open Asset Import Library,这是一个模型加载库,可以导入几十种不同格式的模型文件(同样也可以导出部分模型格式).只要Assimp加载完了模型文件,我们就可 ...
- .Net之时间轮算法(终极版)定时任务
TimeWheelDemo 一个基于时间轮原理的定时器 对时间轮的理解 其实我是有一篇文章(.Net 之时间轮算法(终极版))针对时间轮的理论理解的,但是,我想,为啥我看完时间轮原理后,会采用这样的方 ...
- 第六天python3 函数、参数及参数解构(一)
函数 作用:结构话编程对代码的最基本的封装,一般按照功能组织一段代码,封装的目的是为了复用,减少冗余代码,代码更加简洁.美观,可读易懂: 分类: 内建函数,如max() reversed()等 库函数 ...
- Linux安装mysql8.0.29详细教程
我在上午卸载了陪伴我多年的mysql5.7,现在准备安装mysql8.0. 一.登录mysql官网下载mysql安装包(我的系统是Centos7) MySQL :: Download MySQL ...
- 字符输出流_Writer类&FileWrite类介绍和字符输出流的基本使用_写出单个字符到文件
字符输出流_Writer类&FileWrite类介绍 java.io.Writer:字符输出流,是所有字符输出流的最顶层的父类,是一个抽象类 共性抽象方法: void write(int c) ...