题目描述

在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. 2016-2017-2 20155325实验二《Java面向对象程序设计》实验报告

    实验二 面向对象程序设计-1 答案截图 码云代码链接 链接1 实验遇到的问题和解决过程 问题1:在plugins里搜索不到JUnitGenerator V2.0只能搜到Generste Teats 问 ...

  2. 20155329胡佩伦 《Java程序设计》第3周学习总结

    学号 2016-2017-20155329胡佩伦 <Java程序设计>第3周学习总结 教材学习内容总结 本周复习巩固了运算符. 前缀自增自减法(++i,--i): 先进行自增或者自减运算, ...

  3. 《Java 程序设计》课堂实践项目-mini dc

    <Java 程序设计>课堂实践项目-后缀表达式 课后学习总结 目录 改变 mini dc实验要求 后缀表达式介绍 课堂实践成果 课后思考 改变 修改了博客整体布局,改变了之前贴个截图粘个代 ...

  4. [FJOI2016]建筑师 斯特林数

    早期作品,不喜轻喷. LG传送门 组合数与斯特林数的基本应用. 组合数 大家应该都熟悉它的表达式,但我们这里使用它的递推式会更加方便,下面推导组合数的递推式.设\(\binom{n}{m}\)表示在\ ...

  5. 安装完.net core sdk 后部署 ASP.NET Core 出现错误502.5

    将项目升级到和sdk一样的版本 然后 命令行执行 iisreset

  6. flask ssti python2和python3 注入总结和区别

    总结一下flask ssti的注入语句 代码 import uuid from flask import Flask, request, make_response, session,render_t ...

  7. 【python 3.6】python读取json数据存入MySQL(二)

    在网上找到一个包含全国各省市经纬度的json文件,也可以通过上次的办法,解析json关键字,构造SQL语句,插入数据库. JSON文件格式如下: [ { "name": " ...

  8. hdu - 6277,2018CCPC湖南全国邀请赛B题,找规律,贪心找最优.

    题意: 给出N个小时,分配这些小时去写若干份论文,若用1小时写一份论文,该论文会被引用A次,新写一篇论文的话,全面的论文会被新论文引用一次. 找最大的H,H是指存在H遍论文,而且这些论文各被引用大于H ...

  9. 导出Office365中的组及成员

    Set-ExecutionPolicy unrestricted $cred = Get-Credential  $session = New-PSSession -ConfigurationName ...

  10. [T-ARA][HUE]

    歌词来源:http://music.163.com/#/song?id=22704406 wa du seu mo geum to yo do ga tae 어딜가도 스페셜한게 없어 [eo-dil ...