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大爷题解传送门 说一下感受: 容易发现 ...
随机推荐
- spring @valid 注解
用于验证注解是否符合要求,直接加在变量之前,在变量中添加验证信息的要求,当不符合要求时就会在方法中返回message 的错误提示信息. @PostMapping public User create ...
- AS将一个项目导入到另一个项目中
需求:有项目A,B.需要将B集成到A中,作为A的一个模块. 方法: 1.将B工程的app下面的build.gradle文字中 apply plugin: 'com.android.applicati ...
- python 爬虫--下载图片,下载音乐
#下载图片 imgUrl='http://www.pptbz.com/pptpic/UploadFiles_6909/201211/2012111719294197.jpg' r=requests.g ...
- Eclipse中导入Maven Web项目并配置其在Tomcat中运行
今天因为实习的关系需要讲公司已经开发的项目导入进Eclipse,而公司的项目是用Maven来构建的所以,需要将Maven项目导入进Eclipse下. 自己因为没有什么经验所以搞了得两个多小时,在这里和 ...
- 爬取糗事百科热门段子的数据并保存到本地,xpath的使用
和之前的爬虫类博客的爬取思路基本一致: 构造url_list,因为糗事百科的热门栏目默认是13页,所以这个就简单了 遍历发送请求获取响应 提取数据,这里用的是xpath提取,用的是Python的第三方 ...
- 5表联查yii框架权限控制
一:控制器部分 <?php namespace app\controllers; use yii\web\Controller; class PreController extends Cont ...
- 从入门到自闭之Python while如何使用
while 循环 while 条件: 循环体 终止循环的两种办法: 改变条件 break break和continue的用法: break 用法:打破当前循环,(终止当前循环),所处位置在循环 ...
- 高效编程之 cProfile 性能分析
写代码经常会听说一些名词,比如 性能分析.代码调优. cProfile 是 python 代码调优的一种工具,它能够统计在整个代码执行过程中,每个函数调用的次数和消耗的时间. 这个工具虽然很常用,但是 ...
- Java8 parallelStream浅析
JAVA8中引入了lamda表达式和Stream接口.其丰富的API及强大的表达能力极大的简化代码,提升了效率,同时还通过parallelStream提供并发操作的支持,本文探讨parallelStr ...
- 安装PIG
下载Pig 能够执行在Hadoop 0.20.* http://mirror.bit.edu.cn/apache/pig/pig-0.11.1/pig-0.11.1.tar.gz 也能够依据你的Had ...