zoukankan      html  css  js  c++  java
  • Gym

    题目大意:给出一个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重构树+二维前缀和):

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int N = 1000+10;
     4 char s[N][N];
     5 int n,a[N][N],mxl[N][N],m,Fa[N*N*2],Tot,Q,hd[N*N*2],ne,C[N*N*2];
     6 int fa[N*N*2],son[N*N*2],siz[N*N*2],dep[N*N*2],top[N*N*2];
     7 struct E {int v,nxt;} e[N*N*2];
     8 void addedge(int u,int v) {e[ne]= {v,hd[u]},hd[u]=ne++;}
     9 void dfs1(int u,int f,int d) {
    10     fa[u]=f,son[u]=0,siz[u]=1,dep[u]=d;
    11     for(int i=hd[u]; ~i; i=e[i].nxt) {
    12         int v=e[i].v;
    13         if(v==fa[u])continue;
    14         dfs1(v,u,d+1),siz[u]+=siz[v];
    15         if(siz[v]>siz[son[u]])son[u]=v;
    16     }
    17 }
    18 void dfs2(int u,int tp) {
    19     top[u]=tp;
    20     if(son[u])dfs2(son[u],top[u]);
    21     for(int i=hd[u]; ~i; i=e[i].nxt) {
    22         int v=e[i].v;
    23         if(v==fa[u]||v==son[u])continue;
    24         dfs2(v,v);
    25     }
    26 }
    27 int lca(int u,int v) {
    28     for(; top[u]!=top[v]; u=fa[top[u]])
    29         if(dep[top[u]]<dep[top[v]])swap(u,v);
    30     if(dep[u]<dep[v])swap(u,v);
    31     return v;
    32 }
    33 int sum(int x1,int y1,int x2,int y2) {return a[x2][y2]-a[x1-1][y2]-a[x2][y1-1]+a[x1-1][y1-1];}
    34 int ok(int i,int j,int x) {return !sum(i-x,j-x,i+x,j+x);}
    35 int bi(int i,int j,int l,int r) {
    36     int ret;
    37     while(l<=r) {
    38         int mid=(l+r)>>1;
    39         if(ok(i,j,mid))l=mid+1,ret=mid;
    40         else r=mid-1;
    41     }
    42     return ret;
    43 }
    44 struct E2 {
    45     int x1,y1,x2,y2,c;
    46     bool operator<(const E2& b)const {return c>b.c;}
    47 } e2[N*N*2];
    48 int fd(int x) {return Fa[x]?Fa[x]=fd(Fa[x]):x;}
    49 int id(int x,int y) {return (x-1)*n+(y-1)+1;}
    50 void kruskal() {
    51     sort(e2,e2+m);
    52     Tot=n*n;
    53     memset(hd,-1,sizeof hd),ne=0;
    54     for(int i=1; i<=n; ++i)
    55         for(int j=1; j<=n; ++j)C[id(i,j)]=mxl[i][j];
    56     for(int i=0; i<m; ++i) {
    57         int x1=e2[i].x1,y1=e2[i].y1,x2=e2[i].x2,y2=e2[i].y2,c=e2[i].c;
    58         int fx=fd(id(x1,y1)),fy=fd(id(x2,y2));
    59         if(fx==fy)continue;
    60         int w=++Tot;
    61         C[w]=c;
    62         Fa[fx]=Fa[fy]=w;
    63         addedge(w,fx),addedge(w,fy);
    64     }
    65 }
    66 int main() {
    67     scanf("%d",&n);
    68     for(int i=1; i<=n; ++i)scanf("%s",s[i]+1);
    69     for(int i=1; i<=n; ++i)for(int j=1; j<=n; ++j)a[i][j]=s[i][j]=='#';
    70     for(int i=1; i<=n; ++i)
    71         for(int j=1; j<=n; ++j)
    72             a[i][j]=a[i][j]+a[i-1][j]+a[i][j-1]-a[i-1][j-1];
    73     for(int i=1; i<=n; ++i)
    74         for(int j=1; j<=n; ++j)
    75             mxl[i][j]=s[i][j]=='#'?0:bi(i,j,0,min(min(i-1,n-i),min(j-1,n-j)))*2+1;
    76     for(int i=1; i<=n; ++i)
    77         for(int j=1; j<=n; ++j) {
    78             if(i<n)e2[m++]= {i,j,i+1,j,min(mxl[i][j],mxl[i+1][j])};
    79             if(j<n)e2[m++]= {i,j,i,j+1,min(mxl[i][j],mxl[i][j+1])};
    80         }
    81     kruskal();
    82     dfs1(Tot,0,1),dfs2(Tot,Tot);
    83     scanf("%d",&Q);
    84     while(Q--) {
    85         int x1,y1,x2,y2;
    86         scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
    87         printf("%d
    ",C[lca(id(x1,y1),id(x2,y2))]);
    88     }
    89 }

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

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int N = 1000+10;
     4 char s[N][N];
     5 int n,a[N][N],mxl[N][N],m,fa[N*N],Q,C[N*N],mxd[N*N],dep[N*N];
     6 struct E {
     7     int x1,y1,x2,y2,c;
     8     bool operator<(const E& b)const {return c>b.c;}
     9 } e[N*N*2];
    10 struct D {int x,y;};
    11 queue<D> q;
    12 void upd(int x,int y,int c) {if(!~mxl[x][y])mxl[x][y]=c,q.push({x,y});}
    13 void bfs() {
    14     while(q.size())q.pop();
    15     memset(mxl,-1,sizeof mxl);
    16     for(int i=0; i<=n+1; ++i)
    17         for(int j=0; j<=n+1; ++j)if(i<1||i>n||j<1||j>n||s[i][j]=='#')upd(i,j,0);
    18     while(q.size()) {
    19         int x=q.front().x,y=q.front().y;
    20         q.pop();
    21         for(int x2=x-1; x2<=x+1; ++x2)
    22             for(int y2=y-1; y2<=y+1; ++y2) {
    23                 if(x2<1||x2>n||y2<1||y2>n||~mxl[x2][y2])continue;
    24                 upd(x2,y2,mxl[x][y]+1);
    25             }
    26     }
    27     for(int i=1; i<=n; ++i)
    28         for(int j=1; j<=n; ++j)if(s[i][j]=='.')mxl[i][j]=mxl[i][j]*2-1;
    29 }
    30 int fd(int x) {return fa[x]?fd(fa[x]):x;}
    31 int id(int x,int y) {return (x-1)*n+(y-1)+1;}
    32 int dfs(int u) {if(!fa[u])return 0; if(dep[u])return dep[u]; return dep[u]=dfs(fa[u])+1;}
    33 void kruskal() {
    34     sort(e,e+m);
    35     for(int i=1; i<=n; ++i)
    36         for(int j=1; j<=n; ++j)mxd[id(i,j)]=1;
    37     for(int i=0; i<m; ++i) {
    38         int x1=e[i].x1,y1=e[i].y1,x2=e[i].x2,y2=e[i].y2,c=e[i].c;
    39         int fx=fd(id(x1,y1)),fy=fd(id(x2,y2));
    40         if(fx==fy)continue;
    41         if(mxd[fx]>mxd[fy])swap(fx,fy);
    42         fa[fx]=fy,C[fx]=c,mxd[fy]=max(mxd[fy],mxd[fx]+1);
    43     }
    44     for(int i=1; i<=n; ++i)
    45         for(int j=1; j<=n; ++j)dfs(id(i,j));
    46 }
    47 int qry(int x1,int y1,int x2,int y2) {
    48     int ret=min(mxl[x1][y1],mxl[x2][y2]);
    49     int u=id(x1,y1),v=id(x2,y2);
    50     while(u!=v) {
    51         if(dep[u]<dep[v])swap(u,v);
    52         ret=min(ret,C[u]);
    53         u=fa[u];
    54     }
    55     return ret;
    56 }
    57 int main() {
    58     scanf("%d",&n);
    59     for(int i=1; i<=n; ++i)scanf("%s",s[i]+1);
    60     bfs();
    61     for(int i=1; i<=n; ++i)
    62         for(int j=1; j<=n; ++j) {
    63             if(i<n)e[m++]= {i,j,i+1,j,min(mxl[i][j],mxl[i+1][j])};
    64             if(j<n)e[m++]= {i,j,i,j+1,min(mxl[i][j],mxl[i][j+1])};
    65         }
    66     kruskal();
    67     scanf("%d",&Q);
    68     while(Q--) {
    69         int x1,y1,x2,y2;
    70         scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
    71         printf("%d
    ",qry(x1,y1,x2,y2));
    72     }
    73 }
  • 相关阅读:
    Java设计模式6
    数据库的三范式是什么?
    Mysql 索引的原理和实现
    Java Calendar
    读书-《众病之王:癌症传》-癌症的历史
    Numpy的终极备忘录
    监督学习和kNN分类初学者教程
    用PyTorch实现图像聚类
    Pandas概论
    掌握Python字典的12个例子
  • 原文地址:https://www.cnblogs.com/asdfsag/p/11622902.html
Copyright © 2011-2022 走看看