给你一张地图,给你q次询问,每次问你从A点到B点,最大能移动多大的箱子。

把每个点所能容纳的最大箱子求出来(BFS,八连通,一开始将所有边界点和障碍点入队)。然后从大到小排序。然后用并查集将相邻(四联通)的点依次链接起来,如果不路径压缩的话,那么两个节点的LCA的所能容纳的箱子大小就是答案。于是用并查集辅助建树,之后离线询问,然后Tarjan跑个LCA即可。

O(n^2+qlog(n)),log是因为map记录答案。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
#include<map>
using namespace std;
vector<int>ask[1010*1010];
int dx[]={0,1,0,-1,1,1,-1,-1},dy[]={1,0,-1,0,1,-1,1,-1};
int e,v[1010*1010],first[1010*1010],next[1010*1010];
void AddEdge(int U,int V){
v[++e]=V;
next[e]=first[U];
first[U]=e;
}
struct Point{
int x,y;
Point(const int &x,const int &y){
this->x=x;
this->y=y;
}
Point(){}
};
bool operator < (const Point &a,const Point &b){
return a.x!=b.x ? a.x<b.x : a.y<b.y;
}
map<Point,int>anss;
struct Node{
Point p;
int d;
Node(const Point &p,const int &d){
this->p=p;
this->d=d;
}
};
int n,siz[1010][1010],Siz[1010*1010],m,K;
int id[1010][1010];
bool cmp(const Point &a,const Point &b){
return siz[a.x][a.y]>siz[b.x][b.y];
}
char a[1010][1010];
queue<Node>q;
bool vis[1010][1010];
Point ps[1010*1010];
int fa[1010*1010];
int find(int x){
return x==fa[x] ? x : fa[x]=find(fa[x]);
}
Point qa[300010],qb[300010];
bool not_rt[1010*1010];
int ans[1010*1010];
bool VIS[1010*1010];
void LCA(int u)
{
ans[u]=u;
for(int i=first[u];i;i=next[i])
{
LCA(v[i]);
int f1=find(u),f2=find(v[i]);
fa[f1]=f2;
ans[find(u)]=u;
}
VIS[u]=true;
for(int i=0;i<ask[u].size();i++)
if(VIS[ask[u][i]]){
// printf("%d %d %d %d\n",min(u,ask[u][i]),max(u,ask[u][i]),ans[find(ask[u][i])],Siz[ans[find(ask[u][i])]]);
anss[Point(min(u,ask[u][i]),max(u,ask[u][i]))]=Siz[ans[find(ask[u][i])]];
}
}
bool sb_q[300010];
int main(){
// freopen("h.in","r",stdin);
scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%s",a[i]+1);
}
for(int i=0;i<=n+1;++i){
q.push(Node(Point(i,0),0));
vis[i][0]=1;
q.push(Node(Point(i,n+1),0));
vis[i][n+1]=1;
}
for(int i=0;i<=n+1;++i){
q.push(Node(Point(0,i),0));
vis[0][i]=1;
q.push(Node(Point(n+1,i),0));
vis[n+1][i]=1;
}
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
if(a[i][j]=='#'){
q.push(Node(Point(i,j),0));
vis[i][j]=1;
}
}
}
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
id[i][j]=++m;
}
}
m=0;
while(!q.empty()){
Node U=q.front(); q.pop();
int x=U.p.x,y=U.p.y;
for(int i=0;i<8;++i){
int tx=x+dx[i],ty=y+dy[i];
if(tx>=1 && tx<=n && ty>=1 && ty<=n && !vis[tx][ty]){
q.push(Node(Point(tx,ty),U.d+1));
siz[tx][ty]=Siz[id[tx][ty]]=2*U.d+1;
vis[tx][ty]=1;
}
}
}
// for(int i=1;i<=n;++i){
// for(int j=1;j<=n;++j){
// printf("%d ",siz[i][j]);
// }
// puts("");
// }
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
if(siz[i][j]){
ps[++m]=Point(i,j);
}
}
}
for(int i=1;i<=m;++i){
fa[id[ps[i].x][ps[i].y]]=id[ps[i].x][ps[i].y];
}
sort(ps+1,ps+m+1,cmp);
memset(vis,0,sizeof(vis));
for(int i=1;i<=m;++i){
int x=ps[i].x,y=ps[i].y;
for(int j=0;j<4;++j){
int tx=x+dx[j],ty=y+dy[j];
if(a[tx][ty]=='.' && vis[tx][ty]){
int rt=find(id[tx][ty]);
if(rt!=find(id[x][y])){
AddEdge(id[x][y],rt);
// printf("%d %d\n",id[x][y],rt);
not_rt[rt]=1;
fa[rt]=id[x][y];
}
}
}
vis[x][y]=1;
}
scanf("%d",&K);
for(int i=1;i<=K;++i){
scanf("%d%d%d%d",&qa[i].x,&qa[i].y,&qb[i].x,&qb[i].y);
int f1=find(id[qa[i].x][qa[i].y]),f2=find(id[qb[i].x][qb[i].y]);
if(f1==f2){
ask[id[qa[i].x][qa[i].y]].push_back(id[qb[i].x][qb[i].y]);
ask[id[qb[i].x][qb[i].y]].push_back(id[qa[i].x][qa[i].y]);
}
else{
sb_q[i]=1;
}
}
for(int i=1;i<=m;++i){
fa[id[ps[i].x][ps[i].y]]=id[ps[i].x][ps[i].y];
}
for(int i=1;i<=m;++i){
if(!not_rt[id[ps[i].x][ps[i].y]]){
LCA(id[ps[i].x][ps[i].y]);
}
}
for(int i=1;i<=K;++i){
if(sb_q[i]){
puts("0");
}
else{
printf("%d\n",anss[Point(min(id[qa[i].x][qa[i].y],id[qb[i].x][qb[i].y]),
max(id[qa[i].x][qa[i].y],id[qb[i].x][qb[i].y]))]);
}
}
return 0;
}

【BFS】【并查集】【Tarjan】【LCA】Gym - 101173H - Hangar Hurdles的更多相关文章

  1. Gym - 101173H Hangar Hurdles (kruskal重构树/最小生成树+LCA)

    题目大意:给出一个n*n的矩阵,有一些点是障碍,给出Q组询问,每组询问求两点间能通过的最大正方形宽度. 首先需要求出以每个点(i,j)为中心的最大正方形宽度mxl[i][j],可以用二维前缀和+二分或 ...

  2. P5836 [USACO19DEC]Milk Visits S 从并查集到LCA(最近公共祖先) Tarjan算法 (初级)

    为什么以它为例,因为这个最水,LCA唯一黄题. 首先做两道并查集的练习(估计已经忘光了).简单来说并查集就是认爸爸找爸爸的算法.先根据线索理认爸爸,然后查询阶段如果发现他们的爸爸相同,那就是联通一家的 ...

  3. BZOJ1051:受欢迎的牛(并查集 / Tarjan)

    1051: [HAOI2006]受欢迎的牛 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 8161  Solved: 4460 Description ...

  4. Educational Codeforces Round 1 D. Igor In the Museum bfs 并查集

    D. Igor In the Museum Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/598 ...

  5. 计蒜客 444 / xtuoj 1024 京东的物流路径(并查集+离线lca)或者 (点分治)

    题意:一颗树,定义一条路径的权值等于路径的边权之和,需要求这颗树所有路径中权值的最大值 思路: 考虑到路径权值与点权的最值有关,而最值的问题通常可以通过排序就行处理,于是想到先把点权排序. 容易看出如 ...

  6. hdu 5652 India and China Origins(二分+bfs || 并查集)BestCoder Round #77 (div.2)

    题意: 给一个n*m的矩阵作为地图,0为通路,1为阻碍.只能向上下左右四个方向走.每一年会在一个通路上长出一个阻碍,求第几年最上面一行与最下面一行会被隔开. 输入: 首行一个整数t,表示共有t组数据. ...

  7. BZOJ 1098 [POI2007]办公楼biu(反向图bfs+并查集优化)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1098 [题目大意] 现在有一张图,要求将这张图的点划分为尽量多的分组,对于不同分组的两 ...

  8. BZOJ 4668: 冷战 并查集&&暴力LCA(雾)

    利用并查集按秩合并,保存每个点合并的时间: 求时间时,就一直跳u=fa[u],并记录路径上时间的最大值,代表最后一次合并的时间 #include<cstdio> #include<i ...

  9. HDU ACM 2586 How far away ?LCA-&gt;并查集+Tarjan(离线)算法

    题意:一个村子有n个房子,他们用n-1条路连接起来,每两个房子之间的距离为w.有m次询问,每次询问房子a,b之间的距离是多少. 分析:近期公共祖先问题,建一棵树,求出每一点i到树根的距离d[i],每次 ...

随机推荐

  1. js_数组去重效率对比

    学习javascript已经快两年了,也不知道到了什么程度了. 说说我对javascript的理解,在电脑的世界里,只有数据. 数组,对象,字符串.对这些数据进行操作就可以完成很多业务逻辑,和页面的交 ...

  2. centos 搭建 ss

    download:https://files.cnblogs.com/files/xishaonian/ShadowsocksR-4.7.0-win.7z 使用方法:使用root用户登录,运行以下命令 ...

  3. 【OneNote】使用线性格式输入数学公式

    在OneNote中按Alt+=,就可以开始输入公式. # 对齐公式数组 可以使用@和&来实现,如 \eqarray(x+1&=2@1+2+3+y&=z@3/x&=6)& ...

  4. 【模板】SPOJ FACT0 大数分解 miller-rabin & pollard-rho

    http://www.spoj.com/problems/FACT0/en/ 给一个小于1e15的数,将他分解. miller-rabin & pollard-rho模板 #include & ...

  5. webview loadRequest

    // 所构建的NSURLRequest具有一个依赖于缓存响应的特定策略,cachePolicy取得策略,timeoutInterval取得超时值 [self.yourSite loadRequest: ...

  6. git命令详情

    1.安装 yum install git 2.创建版本库 git init 3.添加文件 git add file.txt 4.提交文件 git commit -m “新增文件” 5.仓库当前状态 g ...

  7. javascript 实现图片放大镜功能

    淘宝上经常用到的一个功能是利用图片的放大镜功能来查看商品的细节 下面我们来实现这样一个功能吧,原理很简单: 实现一个可以随鼠标移动的虚框 在另外一个块中对应显示虚框中的内容 实现思路: 虚框用css中 ...

  8. linux命令(47):rmdir命令

    1.命令格式: rmdir [选项]... 目录... 2.命令功能: 该命令从一个目录中删除一个或多个子目录项,删除某目录时也必须具有对父目录的写权限. 3.命令参数: - p 递归删除目录dirn ...

  9. POJ-1830

    开关问题 Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 6294   Accepted: 2393 Description ...

  10. Eclipse中部署ES源码运行

    https://stackoverflow.com/questions/40924671/how-to-build-elasticsearch-source-code-using-gradle Gra ...