题目描述

在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. 20155330 2016-2017-2 《Java程序设计》第三周学习总结

    20155330 2016-2017-2 <Java程序设计>第三周学习总结 教材学习内容总结 学习目标 区分基本类型与类类型 理解对象的生成与引用的关系 掌握String类和数组 理解封 ...

  2. qbxt的题:运

    运 题意: 包含4,7的数成为幸运数.给一个序列,求多少个长度为k子序列满足:不包含两个及以上的相同的幸运数.(4出现两次就是不合法的,而4,7各出现一次是合法的). 分析: 1e9内幸运数只有2^1 ...

  3. Nginx入门篇(五)之LNMP环境应用

    一.LNMP组合工作原理 (1)用户通过浏览器输入域名请求Nginx web服务: (2)Nginx对请求的资源进行判断,如果是静态资源,则由Nginx返回给用户:如果是动态请求(.php文件),那么 ...

  4. Django视图层详细介绍

    1 视图函数 一个视图函数,简称视图,是一个简单的Python 函数,它接受Web请求并且返回Web响应.响应可以是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一张图片. ...

  5. 人脸检测及识别python实现系列(6)——终篇:从实时视频流识别出“我”

    人脸检测及识别python实现系列(6)——终篇:从实时视频流识别出“我” 终于到了最后一步,激动时刻就要来临了,先平复一下心情,把剩下的代码加上,首先是为Model类增加一个预测函数: #识别人脸 ...

  6. Nginx高性能优化

    #Nginx配置文件优化 worker_processes ; # nginx进程数,建议按照cpu数目来指定,一般为它的倍数. worker_cpu_affinity ; # 为每个进程分配CPU的 ...

  7. webpack Error: Cannot find module 'webpack/lib/Chunk' Extract-text-webpack-plugin 分离CSS

    深入浅出webpack 1.5章节使用Extract-text-webpack-plugin分离css 安装插件后打包提示错误 Error: Cannot find module 'webpack/l ...

  8. join 中的on和where的区别

    数据库在通过连接两张或多张表来返回记录时,都会生成一张中间的临时表, 然后再将这张临时表返回给用户. 在使用left jion时,on和where条件的区别如下: 1.on条件是在生成临时表时使用的条 ...

  9. 【Linux 运维】Linux 目录

    目录 [Linux 运维]Centos7初始化网络配置 [Linux 运维]linux系统修改主机名 [Linux 运维]linux系统关机.重启.注销命令 [Linux 运维]linux系统查看版本 ...

  10. spring JDBC 事务管理

    spring JDBC 事务管理 一.Spring 中的JDBC Spring中封装了JDBC的ORM框架,可以用它来操作数据,不需要再使用外部的OEM框架(MyBatis),一些小的项目用它. 步骤 ...