LG3684 [CERC2016]机棚障碍 Hangar Hurdles
题意
题目描述
你正在评估一些关于一个巨型飞机仓库的建设计划。飞机仓库的地面可以表示为n行n列的网格图,其中每个格子要么是空的,要么有障碍物。行从上到下依次被编号为1到n,列从左到右依次被编号为1到n。
存放飞机零件的大型集装箱能在飞机仓库的地面上自由移动是很重要的。我们可以将每个集装箱看作一个以某个格子为中心的边平行于坐标轴的正方形。对于一个奇数k,一个尺寸为k的集装箱是一个包含k行k列的正方形。一个集装箱的坐标为其中心格子的坐标。集装箱可以向上下左右移动,但不能碰到障碍物,且不能移出仓库的边界。
给定q对格子A_k和B_k,对于每对格子,请找到能从A_k移动到B_k的集装箱的最大尺寸,注意这个尺寸也要是一个奇数。
输入输出格式
输入格式:
第一行包含一个正整数n(2<=n<=1000),表示仓库的尺寸。
接下来n行,每行n个字符,描述整个仓库,其中“.”表示空格子,“#”表示障碍物。
接下来一行包含一个正整数q(1<=q<=300000),表示询问的个数。
接下来q行,每行4个正整数r_A,c_A,r_B,c_B(1<=r_A,c_A,r_B,c_B<=n),分别表示A和B的坐标。
输入数据保证A和B是不同的空格子。
输出格式:
输出q行,每行一个整数,对于每个询问输出最大尺寸,如果不存在解,那么输出0。
输入输出样例
分析
正解就是从每一个障碍出发做八连通bfs,得到每个位置能放多大尺寸的物件(这就是点权),然后从\((a,b)\)到\((c,d)\)的一条路上,经过的点权最小点的点权,就是走这条路径的答案。
所以把每个格子看做一个点,一个格子和其上下左右四个格子连边,边权为这两个格子中较小的点权。做出最大生成树后,查询路径上最小值即可。
然后做法就很多了,我用的是kruskal重构树。
这个算法还有个名字,叫做最小瓶颈生成树。
时间复杂度\(O(n^2 \log n+q \log n)\)
代码
#include<bits/stdc++.h>
#define rg register
#define il inline
#define co const
template<class T>il T read(){
rg T data=0,w=1;rg char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') w=-1;ch=getchar();}
while(isdigit(ch)) data=data*10+ch-'0',ch=getchar();
return data*w;
}
template<class T>il T read(rg T&x) {return x=read<T>();}
typedef long long ll;
co int N=1001,M=2e6+1;
int n,Q,SZ,m;
char mp[N][N];int QAQ[N][N],id[N][N],qx[M],qy[M];
int v[M],ls[M],rs[M],f[M],dep[M],fa[M][21];
struct edge{int x,y,z;}e[M*2];
co int mvx[8]={1,-1,0,0,1,-1,-1,1},mvy[8]={0,0,1,-1,1,-1,1,-1};
bool cmp(co edge&A,co edge&B) {return A.z>B.z;}
void bfs(){
int he=1,ta=0;
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
if(mp[i][j]=='#') ++ta,qx[ta]=i,qy[ta]=j;
else id[i][j]=++SZ,f[SZ]=SZ;
for(int i=1;i<=n;++i) ++ta,qx[ta]=i,qy[ta]=0;
for(int i=1;i<=n;++i) ++ta,qx[ta]=i,qy[ta]=n+1;
for(int i=1;i<=n;++i) ++ta,qx[ta]=0,qy[ta]=i;
for(int i=1;i<=n;++i) ++ta,qx[ta]=n+1,qy[ta]=i;
while(he<=ta){
int x=qx[he],y=qy[he];++he;
for(int i=0;i<8;++i){
int tx=x+mvx[i],ty=y+mvy[i];
if(1<=tx&&tx<=n&&1<=ty&&ty<=n&&mp[tx][ty]!='#'&&!QAQ[tx][ty])
QAQ[tx][ty]=QAQ[x][y]+1,++ta,qx[ta]=tx,qy[ta]=ty;
}
}
}
int findf(int x) {return x==f[x]?x:f[x]=findf(f[x]);}
void kruscal(){
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j){
if(mp[i][j]=='#') continue;
if(i!=1&&mp[i-1][j]!='#')
e[++m]=(edge){id[i][j],id[i-1][j],std::min(QAQ[i][j],QAQ[i-1][j])-1};
if(j!=1&&mp[i][j-1]!='#')
e[++m]=(edge){id[i][j],id[i][j-1],std::min(QAQ[i][j],QAQ[i][j-1])-1};
}
std::sort(e+1,e+1+m,cmp);
for(int i=1;i<=m;++i){
int r1=findf(e[i].x),r2=findf(e[i].y);
if(r1!=r2){
++SZ,v[SZ]=e[i].z,ls[SZ]=r1,rs[SZ]=r2;
f[SZ]=f[r1]=f[r2]=SZ;
}
}
}
void dfs(int x){
for(int i=1;i<=20;++i) fa[x][i]=fa[fa[x][i-1]][i-1];
if(ls[x]) fa[ls[x]][0]=x,dep[ls[x]]=dep[x]+1,dfs(ls[x]);
if(rs[x]) fa[rs[x]][0]=x,dep[rs[x]]=dep[x]+1,dfs(rs[x]);
}
int lca(int x,int y){
if(dep[x]<dep[y]) std::swap(x,y);
for(int i=20;i>=0;--i) if(dep[fa[x][i]]>=dep[y]) x=fa[x][i];
if(x==y) return x;
for(int i=20;i>=0;--i)
if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
int main(){
// freopen(".in","r",stdin),freopen(".out","w",stdout);
read(n);
for(int i=1;i<=n;++i) scanf("%s",mp[i]+1);
bfs(),kruscal();
for(int i=1;i<=SZ;++i) if(findf(i)==i) dep[i]=1,dfs(i);
for(read(Q);Q--;){
int ax,ay,bx,by;
read(ax),read(ay),read(bx),read(by);
int k=lca(id[ax][ay],id[bx][by]);
if(!k) puts("0");
else printf("%d\n",2*v[k]+1);
}
return 0;
}
LG3684 [CERC2016]机棚障碍 Hangar Hurdles的更多相关文章
- [CERC2016]机棚障碍 Hangar Hurdles(kruskal重构树+树上倍增)
题面 \(solution:\) 某蒟蒻的心路历程: 这一题第一眼感觉很奇怪 带障碍物的图,最大的集装箱? 首先想到的就是限制我集装箱大小条件的是什么: 如果我要在某一个点上放一个集装箱且使它最大, ...
- 洛谷 P3684 机棚障碍Hangar Hurdles [CERC2016] 图论
正解: 解题报告: 传送门! 首先不难想到这题主要有两个问题需要解决,一个是预处理出各个点的箱子半径最大值,一个是求ans 然后分别港下QwQ 首先关于预处理要说下昂 预处理有三种方法,分别港下 第一 ...
- Solution -「CERC 2016」「洛谷 P3684」机棚障碍
\(\mathcal{Description}\) Link. 给一个 \(n\times n\) 的网格图,每个点是空格或障碍.\(q\) 次询问,每次给定两个坐标 \((r_1,c_1), ...
- BZOJ.4793.[CERC2016]Hangar Hurdles(Kruskal重构树 BFS)
题目链接 \(Description\) 有一个\(n\times n\)的正方形网格,上面有若干障碍点.\(q\)次询问,每次询问把一个正方形箱子从\((x1,y1)\)推到\((x2,y2)\) ...
- [CERC2016]Hangar Hurdles
你正在评估一些关于一个巨型飞机仓库的建设计划.飞机仓库的地面可以表示为n行n列的网格图,其中每个格子要么是空的,要么有障碍物.行从上到下依次被编号为1到n,列从左到右依次被编号为1到n.存放飞机零件的 ...
- 【BFS】【并查集】【Tarjan】【LCA】Gym - 101173H - Hangar Hurdles
给你一张地图,给你q次询问,每次问你从A点到B点,最大能移动多大的箱子. 把每个点所能容纳的最大箱子求出来(BFS,八连通,一开始将所有边界点和障碍点入队).然后从大到小排序.然后用并查集将相邻(四联 ...
- Gym - 101173H Hangar Hurdles (kruskal重构树/最小生成树+LCA)
题目大意:给出一个n*n的矩阵,有一些点是障碍,给出Q组询问,每组询问求两点间能通过的最大正方形宽度. 首先需要求出以每个点(i,j)为中心的最大正方形宽度mxl[i][j],可以用二维前缀和+二分或 ...
- Excel随机生成数据2
200万耗时大约 10秒以内,输出结果到txt文件. Sub GetPassword() 'by kagawa Dim i&, j&, k&, l&, m&, ...
- 综述-如何克服HTML5的“性工能”障碍
http://ask.dcloud.net.cn/docs HTML5自出现以来,几经风雨,虽看似很有前途,但实际使用问题太多,DCloud为此踩了无数坑.但我们从未放弃,我们加入了W3C,发起了 H ...
随机推荐
- 20170622xlVBA多部门分类汇总同类合并单元格
Public Sub Basic_CodeFrame() AppSettings On Error GoTo ErrHandler Dim StartTime, UsedTime As Variant ...
- Hololens 开发环境配置(转)
转自 Vangos Pterneas, 4 Apr 2016 CPOL 5.00 (1 vote) vote 1vote 2vote 3vote 4vote 5 The past few days h ...
- 双十一用python秒杀京东好货!
好久没用python了,都写不来了. 需要用到selenium 和 Chromedriver: 我只是记录一下几个坑: 第一个坑:自己电脑里安装了两个版本的python ,3.5和3.6 结果我在pi ...
- 41. First Missing Positive *HARD*
Given an unsorted integer array, find the first missing positive integer. For example,Given [1,2,0] ...
- [LeetCode] 29. Divide Two Integers(不使用乘除取模,求两数相除) ☆☆☆
转载:https://blog.csdn.net/Lynn_Baby/article/details/80624180 Given two integers dividend and divisor, ...
- SQL Server 调优系列基础篇 - 子查询运算总结
前言 前面我们的几篇文章介绍了一系列关于运算符的介绍,以及各个运算符的优化方式和技巧.其中涵盖:查看执行计划的方式.几种数据集常用的连接方式.联合运算符方式.并行运算符等一系列的我们常见的运算符.有兴 ...
- 自动化测试框架Taffy
Taffy Taffy是基于nosetests的自动化测试框架. Taffy主要用来测试后台服务(包括且不限于Http, Dubbo/hessian, Webservice, Socket等类型接口) ...
- Oracle 备份与恢复 15 个典型问题
1.问:Oracle11g数据库数据量有50T,每天增量50g左右,该如何制定备份方案,如何验证备份的有效性? 答:50T的数据也不大,运营商的地市级市数据基本都在100T以上了,只要备份环境允许的话 ...
- python中read()、readline()、readlnes()
在python中 1.file.read()直接按原样读取文件,它通常用于将文件内容放到一个字符串变量中,如果文件大于可用内存,则不可能实现这种处理,因为原来文件里面是str_class,所以 fil ...
- 投资银行的IT部门——不同之处与常见误解
投资银行的IT部门——不同之处与常见误解 说了这么多投资银行,投行里面的IT部门究竟是做什么的呢?在过去,投资银行仅靠纸.笔.计算器就能做生意了.但是在今天,所有的部门都要依靠IT技术.交易部门甚至是 ...