题目大意:给出一个n*n的矩阵,有一些点是障碍,给出Q组询问,每组询问求两点间能通过的最大正方形宽度。

首先需要求出以每个点(i,j)为中心的最大正方形宽度mxl[i][j],可以用二维前缀和+二分或者BFS求。

然后每相邻的两个点建一条权值为min(mxl[i][j],mxl[i'][j'])的边,求出整个图的最小生成树(注意边权要从大到小排序,实际上求出的是边权的“最大生成树”)或者kruskal重构树,对于每组询问(x1,y1),(x2,y2),答案为最小生成树上两点间路径的最小边权,或者kruskal重构树上两点LCA的权值。

如果建的是最小生成树,需要启发式合并(或者路径压缩,新开一个fa数组记录合并后的),如果建的是kruskal重构树,则需要弄个树剖或者倍增,加速求LCA的过程。

版本一(kruskal重构树+二维前缀和):

 #include <bits/stdc++.h>
using namespace std;
const int N = +;
char s[N][N];
int n,a[N][N],mxl[N][N],m,Fa[N*N*],Tot,Q,hd[N*N*],ne,C[N*N*];
int fa[N*N*],son[N*N*],siz[N*N*],dep[N*N*],top[N*N*];
struct E {int v,nxt;} e[N*N*];
void addedge(int u,int v) {e[ne]= {v,hd[u]},hd[u]=ne++;}
void dfs1(int u,int f,int d) {
fa[u]=f,son[u]=,siz[u]=,dep[u]=d;
for(int i=hd[u]; ~i; i=e[i].nxt) {
int v=e[i].v;
if(v==fa[u])continue;
dfs1(v,u,d+),siz[u]+=siz[v];
if(siz[v]>siz[son[u]])son[u]=v;
}
}
void dfs2(int u,int tp) {
top[u]=tp;
if(son[u])dfs2(son[u],top[u]);
for(int i=hd[u]; ~i; i=e[i].nxt) {
int v=e[i].v;
if(v==fa[u]||v==son[u])continue;
dfs2(v,v);
}
}
int lca(int u,int v) {
for(; top[u]!=top[v]; u=fa[top[u]])
if(dep[top[u]]<dep[top[v]])swap(u,v);
if(dep[u]<dep[v])swap(u,v);
return v;
}
int sum(int x1,int y1,int x2,int y2) {return a[x2][y2]-a[x1-][y2]-a[x2][y1-]+a[x1-][y1-];}
int ok(int i,int j,int x) {return !sum(i-x,j-x,i+x,j+x);}
int bi(int i,int j,int l,int r) {
int ret;
while(l<=r) {
int mid=(l+r)>>;
if(ok(i,j,mid))l=mid+,ret=mid;
else r=mid-;
}
return ret;
}
struct E2 {
int x1,y1,x2,y2,c;
bool operator<(const E2& b)const {return c>b.c;}
} e2[N*N*];
int fd(int x) {return Fa[x]?Fa[x]=fd(Fa[x]):x;}
int id(int x,int y) {return (x-)*n+(y-)+;}
void kruskal() {
sort(e2,e2+m);
Tot=n*n;
memset(hd,-,sizeof hd),ne=;
for(int i=; i<=n; ++i)
for(int j=; j<=n; ++j)C[id(i,j)]=mxl[i][j];
for(int i=; i<m; ++i) {
int x1=e2[i].x1,y1=e2[i].y1,x2=e2[i].x2,y2=e2[i].y2,c=e2[i].c;
int fx=fd(id(x1,y1)),fy=fd(id(x2,y2));
if(fx==fy)continue;
int w=++Tot;
C[w]=c;
Fa[fx]=Fa[fy]=w;
addedge(w,fx),addedge(w,fy);
}
}
int main() {
scanf("%d",&n);
for(int i=; i<=n; ++i)scanf("%s",s[i]+);
for(int i=; i<=n; ++i)for(int j=; j<=n; ++j)a[i][j]=s[i][j]=='#';
for(int i=; i<=n; ++i)
for(int j=; j<=n; ++j)
a[i][j]=a[i][j]+a[i-][j]+a[i][j-]-a[i-][j-];
for(int i=; i<=n; ++i)
for(int j=; j<=n; ++j)
mxl[i][j]=s[i][j]=='#'?:bi(i,j,,min(min(i-,n-i),min(j-,n-j)))*+;
for(int i=; i<=n; ++i)
for(int j=; j<=n; ++j) {
if(i<n)e2[m++]= {i,j,i+,j,min(mxl[i][j],mxl[i+][j])};
if(j<n)e2[m++]= {i,j,i,j+,min(mxl[i][j],mxl[i][j+])};
}
kruskal();
dfs1(Tot,,),dfs2(Tot,Tot);
scanf("%d",&Q);
while(Q--) {
int x1,y1,x2,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
printf("%d\n",C[lca(id(x1,y1),id(x2,y2))]);
}
}

版本二(最小生成树+BFS):

 #include <bits/stdc++.h>
using namespace std;
const int N = +;
char s[N][N];
int n,a[N][N],mxl[N][N],m,fa[N*N],Q,C[N*N],mxd[N*N],dep[N*N];
struct E {
int x1,y1,x2,y2,c;
bool operator<(const E& b)const {return c>b.c;}
} e[N*N*];
struct D {int x,y;};
queue<D> q;
void upd(int x,int y,int c) {if(!~mxl[x][y])mxl[x][y]=c,q.push({x,y});}
void bfs() {
while(q.size())q.pop();
memset(mxl,-,sizeof mxl);
for(int i=; i<=n+; ++i)
for(int j=; j<=n+; ++j)if(i<||i>n||j<||j>n||s[i][j]=='#')upd(i,j,);
while(q.size()) {
int x=q.front().x,y=q.front().y;
q.pop();
for(int x2=x-; x2<=x+; ++x2)
for(int y2=y-; y2<=y+; ++y2) {
if(x2<||x2>n||y2<||y2>n||~mxl[x2][y2])continue;
upd(x2,y2,mxl[x][y]+);
}
}
for(int i=; i<=n; ++i)
for(int j=; j<=n; ++j)if(s[i][j]=='.')mxl[i][j]=mxl[i][j]*-;
}
int fd(int x) {return fa[x]?fd(fa[x]):x;}
int id(int x,int y) {return (x-)*n+(y-)+;}
int dfs(int u) {if(!fa[u])return ; if(dep[u])return dep[u]; return dep[u]=dfs(fa[u])+;}
void kruskal() {
sort(e,e+m);
for(int i=; i<=n; ++i)
for(int j=; j<=n; ++j)mxd[id(i,j)]=;
for(int i=; i<m; ++i) {
int x1=e[i].x1,y1=e[i].y1,x2=e[i].x2,y2=e[i].y2,c=e[i].c;
int fx=fd(id(x1,y1)),fy=fd(id(x2,y2));
if(fx==fy)continue;
if(mxd[fx]>mxd[fy])swap(fx,fy);
fa[fx]=fy,C[fx]=c,mxd[fy]=max(mxd[fy],mxd[fx]+);
}
for(int i=; i<=n; ++i)
for(int j=; j<=n; ++j)dfs(id(i,j));
}
int qry(int x1,int y1,int x2,int y2) {
int ret=min(mxl[x1][y1],mxl[x2][y2]);
int u=id(x1,y1),v=id(x2,y2);
while(u!=v) {
if(dep[u]<dep[v])swap(u,v);
ret=min(ret,C[u]);
u=fa[u];
}
return ret;
}
int main() {
scanf("%d",&n);
for(int i=; i<=n; ++i)scanf("%s",s[i]+);
bfs();
for(int i=; i<=n; ++i)
for(int j=; j<=n; ++j) {
if(i<n)e[m++]= {i,j,i+,j,min(mxl[i][j],mxl[i+][j])};
if(j<n)e[m++]= {i,j,i,j+,min(mxl[i][j],mxl[i][j+])};
}
kruskal();
scanf("%d",&Q);
while(Q--) {
int x1,y1,x2,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
printf("%d\n",qry(x1,y1,x2,y2));
}
}

Gym - 101173H Hangar Hurdles (kruskal重构树/最小生成树+LCA)的更多相关文章

  1. BZOJ.4793.[CERC2016]Hangar Hurdles(Kruskal重构树 BFS)

    题目链接 \(Description\) 有一个\(n\times n\)的正方形网格,上面有若干障碍点.\(q\)次询问,每次询问把一个正方形箱子从\((x1,y1)\)推到\((x2,y2)\) ...

  2. BZOJ3732Network——kruskal重构树+倍增+LCA/最小生成树+倍增

    题目描述 给你N个点的无向图 (1 <= N <= 15,000),记为:1…N. 图中有M条边 (1 <= M <= 30,000) ,第j条边的长度为: d_j ( 1 & ...

  3. 【BZOJ 3732】 Network Kruskal重构树+倍增LCA

    Kruskal重构树裸题, Sunshine互测的A题就是Kruskal重构树,我通过互测了解到了这个神奇的东西... 理解起来应该没什么难度吧,但是我的Peaks连WA,,, 省选估计要滚粗了TwT ...

  4. 【BFS】【并查集】【Tarjan】【LCA】Gym - 101173H - Hangar Hurdles

    给你一张地图,给你q次询问,每次问你从A点到B点,最大能移动多大的箱子. 把每个点所能容纳的最大箱子求出来(BFS,八连通,一开始将所有边界点和障碍点入队).然后从大到小排序.然后用并查集将相邻(四联 ...

  5. 水壶-[Kruskal重构树] [解题报告]

    水壶 本来从不写针对某题的题解,但因为自己实在是太蠢了,这道题也神TM的恶心,于是就写篇博客纪念一下 H水壶 时间限制 : 50000 MS 空间限制 : 565536 KB 评测说明 : 2s,51 ...

  6. CF1253F Cheap Robot(神奇思路,图论,最短路,最小生成树/Kruskal 重构树/并查集)

    神仙题. 先考虑平方级别的暴力怎么做. 明显答案有单调性,先二分 \(c\). 先最短路预处理 \(dis_u\) 表示 \(u\) 到离它最近的充电站的距离(一开始把 \(1\) 到 \(k\) 全 ...

  7. [bzoj 3732] Network (Kruskal重构树)

    kruskal重构树 Description 给你N个点的无向图 (1 <= N <= 15,000),记为:1-N. 图中有M条边 (1 <= M <= 30,000) ,第 ...

  8. 【BZOJ-3545&3551】Peaks&加强版 Kruskal重构树 + 主席树 + DFS序 + 倍增

    3545: [ONTAK2010]Peaks Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1202  Solved: 321[Submit][Sta ...

  9. BZOJ 3551: [ONTAK2010]Peaks加强版 [Kruskal重构树 dfs序 主席树]

    3551: [ONTAK2010]Peaks加强版 题意:带权图,多组询问与一个点通过边权\(\le lim\)的边连通的点中点权k大值,强制在线 PoPoQQQ大爷题解传送门 说一下感受: 容易发现 ...

随机推荐

  1. 【Web】jquery合并单元格

    合并单元格的情况,在开发中还是比较多见的,以下仅介绍合并行的情况. 原来的table效果 效果如下: 代码如下: <!DOCTYPE html> <html xmlns=" ...

  2. RDD实例

    实例一: teacher.log http://bigdata.baidu.cn/zhangsan http://bigdata.baidu.cn/zhangsan http://bigdata.ba ...

  3. gulp4.0配置

    var gulp = require('gulp'); var rename = require('gulp-rename');//重命名 var uglify=require('gulp-uglif ...

  4. 【AMAD】betamax -- 一个ruby-VCR的模仿品,只支持requests

    简介 动机 作用 用法 个人评分 简介 betamax1会记录你的HTTP操作,可以让你在测试的时候不必重复进行真实的请求. 动机 如果你的代码需要和外部资源一起运作,那么测试这段代码的方法就叫做集成 ...

  5. VMware Workstation 15 Pro简化安装Kali Linux 2019.2

    记录下简单安装的步骤

  6. idea自动化部署插件 Alibaba Cloud Toolkit 使用记录

    官方安装文档和使用说明 https://help.aliyun.com/product/29966.html?spm=a2c4g.11186623.6.540.6efa6029JhlPfx 是什么? ...

  7. Kafka的知识总结

    前言 转自(https://www.cnblogs.com/zhuifeng523/p/12081204.html) Kafka是最初由Linkedin公司开发,是一个分布式.支持分区的(partit ...

  8. Linux下安装双JDK环境与双服务器

    安装双JDK环境和双服务器,具体操作如下: (1)使用tar -xvf命令解压Tomcat: (2)在Tomcat服务器下的bin文件夹下的catalina.sh文件中的头部加入以下内容: (3)修改 ...

  9. Java 中的动态代理

    一.概述 1. 什么是代理 我们大家都知道微商代理,简单地说就是代替厂家卖商品,厂家“委托”代理为其销售商品.关于微商代理,首先我们从他们那里买东西时通常不知道背后的厂家究竟是谁,也就是说,“委托者” ...

  10. MacOS上安装Anaconda+Pycharm+TensorFlow+Keras

    一.安装Anaconda 登录https://www.anaconda.com/download/#macos,下载Anaconda3-5.3.1-MacOSX-x86_64.pkg 二.安装Pych ...