Gym - 101173H Hangar Hurdles (kruskal重构树/最小生成树+LCA)
题目大意:给出一个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)的更多相关文章
- BZOJ.4793.[CERC2016]Hangar Hurdles(Kruskal重构树 BFS)
题目链接 \(Description\) 有一个\(n\times n\)的正方形网格,上面有若干障碍点.\(q\)次询问,每次询问把一个正方形箱子从\((x1,y1)\)推到\((x2,y2)\) ...
- BZOJ3732Network——kruskal重构树+倍增+LCA/最小生成树+倍增
题目描述 给你N个点的无向图 (1 <= N <= 15,000),记为:1…N. 图中有M条边 (1 <= M <= 30,000) ,第j条边的长度为: d_j ( 1 & ...
- 【BZOJ 3732】 Network Kruskal重构树+倍增LCA
Kruskal重构树裸题, Sunshine互测的A题就是Kruskal重构树,我通过互测了解到了这个神奇的东西... 理解起来应该没什么难度吧,但是我的Peaks连WA,,, 省选估计要滚粗了TwT ...
- 【BFS】【并查集】【Tarjan】【LCA】Gym - 101173H - Hangar Hurdles
给你一张地图,给你q次询问,每次问你从A点到B点,最大能移动多大的箱子. 把每个点所能容纳的最大箱子求出来(BFS,八连通,一开始将所有边界点和障碍点入队).然后从大到小排序.然后用并查集将相邻(四联 ...
- 水壶-[Kruskal重构树] [解题报告]
水壶 本来从不写针对某题的题解,但因为自己实在是太蠢了,这道题也神TM的恶心,于是就写篇博客纪念一下 H水壶 时间限制 : 50000 MS 空间限制 : 565536 KB 评测说明 : 2s,51 ...
- CF1253F Cheap Robot(神奇思路,图论,最短路,最小生成树/Kruskal 重构树/并查集)
神仙题. 先考虑平方级别的暴力怎么做. 明显答案有单调性,先二分 \(c\). 先最短路预处理 \(dis_u\) 表示 \(u\) 到离它最近的充电站的距离(一开始把 \(1\) 到 \(k\) 全 ...
- [bzoj 3732] Network (Kruskal重构树)
kruskal重构树 Description 给你N个点的无向图 (1 <= N <= 15,000),记为:1-N. 图中有M条边 (1 <= M <= 30,000) ,第 ...
- 【BZOJ-3545&3551】Peaks&加强版 Kruskal重构树 + 主席树 + DFS序 + 倍增
3545: [ONTAK2010]Peaks Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1202 Solved: 321[Submit][Sta ...
- BZOJ 3551: [ONTAK2010]Peaks加强版 [Kruskal重构树 dfs序 主席树]
3551: [ONTAK2010]Peaks加强版 题意:带权图,多组询问与一个点通过边权\(\le lim\)的边连通的点中点权k大值,强制在线 PoPoQQQ大爷题解传送门 说一下感受: 容易发现 ...
随机推荐
- Eclipse 4.11 Debug jar包代码时进入空心J
代码调试时,进入jar包中的时候,会出现如下的情况超级影响代码调试 断点打在上面的地方,但是却进入到了空心J的那个地方了. 解决办法:去掉勾选即可. 我是这么解决的.
- XCTF (app1)
打开app.一个文本框,随便输入提示如下图. 打开JEB反编译. v2调用getPackageInfo获取版本信息.一般 Android 通过 PackageInfo 这个类来获取应用安装包信息,比如 ...
- SQLServer2008R2复制发布订阅(含局域网跨网段)调试总结
需要注意的问题点: 一.发布服务器A和订阅服务器B都在同一个网段的局域网内 1.两台服务器的SQLServer版本必须一致. 2.两服务器之间访问没难度,直接就可以搜索到. 3.注意请求订阅和推送订阅 ...
- Java架构师 成长之路 -- 跳出程序员陷阱(转载)
本人也是coding很多年,虽然很失败,但也总算有点失败的心得,不过我在中国,大多数程序员都是像我一样,在一直走着弯路. 如果想成为一个架构师,就必须走正确的路,否则离目标越来越远,正在辛苦工作的程序 ...
- Android Studio出现:Cause: unable to find valid certification path to requested target
我的AS版本是3.4.1..出现这个问题是因为公司内网很奇葩,连上后必须访问一次网页.所以是AS连不上网络,访问不了https://bintray.com/bintray/jcenter导致的.
- Mongo分片+副本集集群搭建
一. 概念简单描述 1. MongoDB分片集群包含组件: mongos,configserver,shardding分片 2. Mongos:路由服务是Sharded cluster的访问入口,本身 ...
- 2019牛客暑期多校训练营(第二场)-F artition problem
题目链接:https://ac.nowcoder.com/acm/contest/882/F 题意:将2×n个人分成两组,每组n个人,求一个组中所有人和另外一组的所有人的竞争值之和. 思路: 比赛时看 ...
- (5.8)mysql高可用系列——MySQL中的GTID复制(实践篇)
一.基于GTID的异步复制(一主一从)无数据/少数据搭建 二.基于GTID的无损半同步复制(一主一从)(mysql5.7)基于大数据量的初始化 正文: [0]概念 [0.5]GTID 复制(mysql ...
- iframe高度/宽度自适应(使用body而不是docuemntElement对象)
iframe在ie11中会显示过于短.为了自适应,增加如下代码: <iframe *** onload='changeFrameHeight()' > <script> fun ...
- codeforces 816B Karen and Coffee (差分思想)
题目链接 816B Karen and Coffee 题目分析 题意:有个人在学泡咖啡,因此看了很多关于泡咖啡温度的书,得到了n种推荐的泡咖啡温度范围[L1,R1] ,此人将有k种做法推荐的温度记为可 ...