题目描述

在Byteland的首都,有一个矩形围栏围起来的公园。在这个公园里树和访客都以一个圆形表示。公园有四个出入口,每个角落一个(1=左下角,2=右下角,3=右上角,4=左上角)。访客能通过这些出入口进出公园。访客在同时碰到一个角落的两条边时就可以通过该角落进出公园。访客在公园里可以自由地移动,但他们不能和树和围栏相交。对于每个访客,给定他们进入公园的出入口,你的任务是计算他们能在哪个出入口离开公园。

输入

输入的第一行包含两个整数:n,m:树的数量和访客的数量。
第二行包含两个整数:w,h:公园的宽和高。左下角的坐标是(0,0),右上角的坐标是(w,h)。
接下来的n行描述每棵树。
每行包含3个整数:x,y,r:树的圆心是(x,y),半径是r。每棵树都不会和其他树和围栏相交。
最后m行描述每个访客。每行包含2个整数:r,e:访客的半径和他们进入公园的出入口。
数据保证没有一棵树会和每个角落的2k*2k的方形区域相交,k是最大的访客半径。
1<=N<=2000
1<=M<=100000
4k<w,h<=10^9

输出

对于每个访客你要输出一行,包含了他们能在哪些出入口离开公园,以从小到大的顺序输出,不需要空格分隔。

样例输入

5 3
16 11
11 8 1
6 10 1
7 3 2
10 4 1
15 5 1
1 1
2 2
2 1

样例输出

1234
2
14


题解

离线+对偶图+并查集

套路:如果两棵树或树与边界之间无法通过,则视作它们之间连了一条边。

那么左下角能到右下角等价于:下边界与左、上、右边界都不连通。其余同理。

然而每个人的半径都不同,对每个人单独处理必T无疑。考虑离线,将人按照半径、树与树和树与边界按照能通过的最大距离从小到大排序然后处理即可。

连通性可以直接使用并查集维护。

时间复杂度 $O(n^2\log n+m\log m+m\times 常数)$

#include <cmath>
#include <cstdio>
#include <algorithm>
#define squ(x) (x) * (x)
using namespace std;
struct data
{
double d;
int x , y;
data() {}
data(double a , int b , int c) {d = a , x = b , y = c;}
bool operator<(const data &a)const {return d < a.d;}
}a[2007010] , q[100010];
double px[2010] , py[2010] , pr[2010];
int f[2010] , ans[100010] , tot;
int find(int x)
{
return x == f[x] ? x : f[x] = find(f[x]);
}
int main()
{
int n , m , i , j , p = 1 , t1 , t2 , t3 , t4;
double w , h;
scanf("%d%d%lf%lf" , &n , &m , &w , &h);
for(i = 1 ; i <= n ; i ++ )
{
scanf("%lf%lf%lf" , &px[i] , &py[i] , &pr[i]);
a[++tot] = data(px[i] - pr[i] , i , n + 1);
a[++tot] = data(py[i] - pr[i] , i , n + 2);
a[++tot] = data(w - px[i] - pr[i] , i , n + 3);
a[++tot] = data(h - py[i] - pr[i] , i , n + 4);
for(j = 1 ; j < i ; j ++ ) a[++tot] = data(sqrt(squ(px[i] - px[j]) + squ(py[i] - py[j])) - pr[i] - pr[j] , i , j);
}
for(i = 1 ; i <= m ; i ++ ) scanf("%lf%d" , &q[i].d , &q[i].x) , q[i].d *= 2 , q[i].y = i;
sort(a + 1 , a + tot + 1) , sort(q + 1 , q + m + 1);
for(i = 1 ; i <= n + 4 ; i ++ ) f[i] = i;
for(i = 1 ; i <= m ; i ++ )
{
while(p <= tot && a[p].d < q[i].d) f[find(a[p].x)] = find(a[p].y) , p ++ ;
t1 = find(n + 1);
t2 = find(n + 2);
t3 = find(n + 3);
t4 = find(n + 4);
if(q[i].x == 1)
{
ans[q[i].y] |= (1 << 1);
if(t2 != t1 && t2 != t3 && t2 != t4) ans[q[i].y] |= (1 << 2);
if(t1 != t2 && t1 != t3 && t2 != t4 && t3 != t4) ans[q[i].y] |= (1 << 3);
if(t1 != t2 && t1 != t3 && t1 != t4) ans[q[i].y] |= (1 << 4);
}
else if(q[i].x == 2)
{
ans[q[i].y] |= (1 << 2);
if(t2 != t1 && t2 != t3 && t2 != t4) ans[q[i].y] |= (1 << 1);
if(t3 != t1 && t3 != t2 && t3 != t4) ans[q[i].y] |= (1 << 3);
if(t1 != t3 && t1 != t4 && t2 != t3 && t2 != t4) ans[q[i].y] |= (1 << 4);
}
else if(q[i].x == 3)
{
ans[q[i].y] |= (1 << 3);
if(t1 != t2 && t1 != t3 && t2 != t4 && t3 != t4) ans[q[i].y] |= (1 << 1);
if(t3 != t1 && t3 != t2 && t3 != t4) ans[q[i].y] |= (1 << 2);
if(t4 != t1 && t4 != t2 && t4 != t3) ans[q[i].y] |= (1 << 4);
}
else
{
ans[q[i].y] |= (1 << 4);
if(t1 != t2 && t1 != t3 && t1 != t4) ans[q[i].y] |= (1 << 1);
if(t1 != t3 && t1 != t4 && t2 != t3 && t2 != t4) ans[q[i].y] |= (1 << 2);
if(t4 != t1 && t4 != t2 && t4 != t3) ans[q[i].y] |= (1 << 3);
}
}
for(i = 1 ; i <= m ; i ++ )
{
for(j = 1 ; j <= 4 ; j ++ )
if(ans[i] & (1 << j))
printf("%d" , j);
puts("");
}
return 0;
}

【bzoj5183】[Baltic2016]Park 离线+对偶图+并查集的更多相关文章

  1. 【bzoj3007】拯救小云公主 二分+对偶图+并查集

    题目描述 英雄又即将踏上拯救公主的道路…… 这次的拯救目标是——爱和正义的小云公主. 英雄来到boss的洞穴门口,他一下子就懵了,因为面前不只是一只boss,而是上千只boss.当英雄意识到自己还是等 ...

  2. bzoj5183 [Baltic2016]Park

    题目描述: bz luogu 题解: 把坐标系看反了持续$WA$系列. 对偶图+并查集维护. 先处理出树对树.树对墙的空隙,然后把人和空隙按从小到大排序. 用并查集维护四面墙之间是否能互相隔断. 代码 ...

  3. BZOJ_4423_[AMPPZ2013]Bytehattan_对偶图+并查集

    BZOJ_4423_[AMPPZ2013]Bytehattan_对偶图+并查集 Description 比特哈顿镇有n*n个格点,形成了一个网格图.一开始整张图是完整的. 有k次操作,每次会删掉图中的 ...

  4. 【BZOJ4423】[AMPPZ2013]Bytehattan 对偶图+并查集

    [BZOJ4423][AMPPZ2013]Bytehattan Description 比特哈顿镇有n*n个格点,形成了一个网格图.一开始整张图是完整的.有k次操作,每次会删掉图中的一条边(u,v), ...

  5. 【bzoj4423】[AMPPZ2013]Bytehattan(平面图转对偶图+并查集)

    题目传送门:bzoj4423 如果是普通的删边判连通性,我们可以很显然的想到把操作离线下来,倒着加边.然而,这题强 制 在 线. 虽然如此,但是题目所给的图是个平面图.那么我们把它转成对偶图试试看? ...

  6. HDU 5441 离线处理 + 并查集

    题意:给n个节点m条带权值边的无向图.然后q个问题,每次询问点对的数目,点对需要满足的条件是:1)连通:2)其路径的最大权值不能超过询问值. 分析:如果没次询问一次,dfs一次,很可能超时,因此可以用 ...

  7. 对偶图 并查集 BZOJ4423

    题目链接 题目因为要根据上一次的输出结果来判断这次的输入,也就是要求我们强制在线,不能够把输入全部储存后处理 如果不要求强制在线,我们可以先把所以输入储存起来,从最后开始处理,把删边改成加边,如果在加 ...

  8. [BZOJ4423][AMPPZ2013]Bytehattan(对偶图+并查集)

    建出对偶图,删除一条边时将两边的格子连边.一条边两端连通当且仅当两边的格子不连通,直接并查集处理即可. #include<cstdio> #include<algorithm> ...

  9. hdu Portal(离线,并查集)

    题意:在一张无向图上,已知边权,做q组询问,问小于L的点对共有几组.点对间的距离取=min(两点之间每一条通路上的最大值). 分析:这里取最大值的最小值,常用到二分.而这里利用离线算法,先对边从小到大 ...

随机推荐

  1. High Water Mark 图示

    +---- high water mark of newly created table | V +-------------------------------------------------- ...

  2. 【转】CentOS Linux解决Device eth0 does not seem to be present(linux)

    原文来自:http://www.linuxidc.com/Linux/2012-12/76248.htm 在VMware里克隆出来的CentOS Linux.. ifconfig...没有看到eth0 ...

  3. 基于OpenSSL的RSA加密应用(非算法)

    基于OpenSSL的RSA加密应用(非算法) iOS开发中的小伙伴应该是经常用der和p12进行加密解密,而且在通常加密不止一种加密算法,还可以加点儿盐吧~本文章主要阐述的是在iOS中基于openSL ...

  4. Redis主从复制(Master/Slave) 与哨兵模式

    Redis主从复制是什么? 行话:也就是我们所说的主从复制,主机数据更新后根据配置和策略, 自动同步到备机的master/slaver机制,Master以写为主,Slave以读为主 Redis主从复制 ...

  5. redis sentinel介绍

    目录 配置redis主从复制 使用ping命令检查是否启动 主节点查看链接信息 开始部署sentinel 节点 部署sentinel 启动sentinel 演示下故障转移 查看当前sentinel监控 ...

  6. ubuntu/linux系统中安装jdk以及eclipse(附图解详细步骤)

    1.首先得先下载JDK和eclipsejdk下载网址:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-21 ...

  7. spring cloud 入门系列七:基于Git存储的分布式配置中心--Spring Cloud Config

    我们前面接触到的spring cloud组件都是基于Netflix的组件进行实现的,这次我们来看下spring cloud 团队自己创建的一个全新项目:Spring Cloud Config.它用来为 ...

  8. MySQL事务、并发问题、锁机制

    MySQL事务,并发问题,锁机制 1.什么是事务 事务是一条或多条数据库操作语句的组合,具备ACID,4个特点. 原子性:要不全部成功,要不全部撤销 隔离性:事务之间相互独立,互不干扰 一致性:数据库 ...

  9. 当git遇上中文乱码

    git有个比较奇怪的问题,当目录或者文件名中出现了中文的时候,在执行git status 的时候,会返回一串unicode码,这段unicode码就读不懂了,必须解决. git status显示uni ...

  10. 完美的【去重留一】SQL

    DELETE consum_record FROM consum_record, ( SELECT min(id) id, user_id, monetary, consume_time FROM c ...