给你一张地图,给你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. windows下安装python过程

    方法一:如果你的电脑没有安装python,推荐使用anaconda(自带python环境,同时自带各种第三方库,可以省去很多麻烦) 这里提供两个下载地址:1,.官网https://www.anacon ...

  2. cuda中的二分查找

    使用背景 通常,在做高性能计算时,我们需要随机的连接某些点.这些点都具有自己的度量值,显然,度量值越大的值随机到的概率就会越大.因此,采用加权值得方法: void getdegreeSum(DG *g ...

  3. Educational Codeforces Round 23 补题小结

    昨晚听说有教做人场,去补了下玩. 大概我的水平能做个5/6的样子? (不会二进制Trie啊,我真菜) A. 傻逼题.大概可以看成向量加法,判断下就好了. #include<iostream> ...

  4. Android ADT插件更新后程序运行时抛出java.lang.VerifyError异常解决办法

    当我把Eclipse中的 Android ADT插件从21.1.0更新到22.0.1之后,安装后运行程序抛出java.lang.VerifyError异常. 经过调查,终于找到了一个有效的解决办法: ...

  5. NOIP 2013 day1

    tags: 模拟 快速幂 逆序对 树状数组 归并排序 最小生成树 lca 倍增 categories: 信息学竞赛 总结 tex live 2017.iso 转圈游戏 火柴排队 货车运输 转圈游戏 s ...

  6. 一个大div里面包裹一个小div,里面的小div的点击事件不触发外面的这个大div的点击事件

    一开始上html代码 <div id="div1" style="background: blue;width: 100px; height: 100px;&quo ...

  7. Flask 通过扩展来实现登录验证

    1. flask扩展 说明: flask的扩展类似于python中的装饰器,和Django中的process_request的方法也类似 测试代码 from flask import Flask,se ...

  8. 《逐梦旅程 WINDOWS游戏编程之从零开始》笔记2——透明贴图,动画技术

    第5章 透明贴图 像这样直接贴图会产生这种情况,所以我们需要透明贴图. 透明遮罩法:主要利用BitBlt函数中Raser(光栅)值的运算,需要准备素材图和遮罩图: 这个方法的原理解释见书131页. 示 ...

  9. 《java并发编程实战》读书笔记2--对象的共享,可见性,安全发布,线程封闭,不变性

    这章的主要内容是:如何共享和发布对象,从而使它们能够安全地由多个线程同时访问. 内存的可见性 确保当一个线程修改了对象状态后,其他线程能够看到发生的状态变化. 上面的程序中NoVisibility可能 ...

  10. 深度学习方法:受限玻尔兹曼机RBM(一)基本概念

    欢迎转载,转载请注明:本文出自Bin的专栏blog.csdn.net/xbinworld. 技术交流QQ群:433250724,欢迎对算法.技术.应用感兴趣的同学加入. 最近在复习经典机器学习算法的同 ...