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大爷题解传送门 说一下感受: 容易发现 ...
随机推荐
- YAML基础知识及搭建一台简洁版guestbook
一,前言 前面我们已经搭建过简易版k8s集群了,在此基础上可以搭建一个简洁版guestbook ,以便来学习k8s创建pod的整个过程. 二,在此之前,我们还需要学习一下YAML基础知识 YAML 基 ...
- app测试自动化操作方法之二
3.进行APP的滑动操作 方法一:#获取窗口大小def get_size(): size=dr.get_window_size() return size print(get_size())#向上滑动 ...
- 云计算共享组件--Memcache缓存系统(4)
一.缓存系统 一.静态web页面: 1.在静态Web程序中,客户端使用Web浏览器(IE.FireFox等)经过网络(Network)连接到服务器上,使用HTTP协议发起一个请求(Request),告 ...
- 【VS开发】static、extern分析总结
引用请注明出处:http://blog.csdn.net/int64ago/article/details/7396325 对于写了很多小程序的人,可能static和extern都用的很少,因为sta ...
- Identification of Encryption Algorithm Using Decision Tree
本文主要做了两件事,一是提出了一种使用C4.5算法生成的决策树来识别密文所使用的加密算法的方法,二是为这一算法设计了一个特征提取系统提取八个特征作为算法的输入,最终实现了70%~75的准确率. 准备工 ...
- 包含时间的Json序列化
public static string ObjectToJson<T>(T t) { using (MemoryStream ms = new MemoryStream()) { Dat ...
- Prometheus 和 Alertmanager实战配置
Prometheus时序数据库 一.Prometheus 1.Prometheus安装 1)源码安装 prometheus安装包最新版本下载地址:https://prometheus.io/downl ...
- bfs(太空电梯)
http://oj.jxust.edu.cn/contest/problem?id=1563&pid=4 题目描述 公元9012年,Q博士发明了一部太空电梯,与一般电梯不同,太空电梯不能直接到 ...
- C++练习 | 基于栈的中缀算术表达式求值(double类型
#include<iostream> #include<stack> #include<cmath> using namespace std; char ch; b ...
- linux centos 7.3 编译安装mysql5.7
#安装依赖 yum update yum install -y gcc gcc-c++ make libtool zlib zlib-devel openssl openssl-devel pcre ...