[CERC2016]机棚障碍 Hangar Hurdles(kruskal重构树+树上倍增)

题面



$ solution: $

某蒟蒻的心路历程:

这一题第一眼感觉很奇怪
带障碍物的图,最大的集装箱?
首先想到的就是限制我集装箱大小条件的是什么:
如果我要在某一个点上放一个集装箱且使它最大,
那就相当于求这一个点往外扩出去的最大正方形。
然后考虑从一个点到与它相邻的点移动时最大的箱子,
这不就是这两个点的最大正方形中较小的那一个吗?
于是考虑把所有点上的最大正方形都求出来,这个n^2即可
然后我就是要求两个点之间所有路径上的最小的那个最大正方形了
仔细一想,嗯?,这不就是货车运输吗?难道我要切题了?
但毕竟被虐的太多了,还是理智的看一遍吧
哇,边数最多可以达到1000000条,我记得火车运输范围只有10000来着?
我靠,要凉啊,算了直接写暴力得了!(然而,……..)

这一道题,仔细审一下题面我们可以发现:在每一个位置上箱子都有一个初始大小,而它如果要移动到与它中心相邻的某一个点上,他的大小又会受到它要移动到的那个点。所以我们可以先跑一遍BFS来求出没一点的初始最大正方形(这个我们可以反过来,从障碍物出发向四周扩展,每个点只会进队一次,复杂度完全可以接受)。然后我们对任何一对相邻的点连边,边权即为两个中最大正方形较小的那一个。这样我们如果要求两条点可以运输的最大正方形,就是求他们之间所有路径中最小权值最大的那一个,而这不就是货车运输吗????(好吧,其实LCA十分容易被卡,所以建议用树链剖分)



$ code: $

#include<iostream>
#include<cstdio>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>

#define ll long long
#define db double
#define inf 0x7fffffff
#define rg register int

using namespace std;

struct su{
    int x,y,v;
    bool operator <(su x){return v>x.v;}
}b[2000005];

struct pi{
    int x,y,v;
}t[2000005];

struct ya{
    int to,v,next;
}d[2000005];

int n,m,tt,top,ttt,xx,yy,ans;
int a[1000005];
int tou[1000005];
int s[1005][1005];
bool k[1005][1005];
char c[1005];
bool vis[1000005];
int dp[1000005];
int lg[1000005];
int f[1000005][20];
int st[1000005][20];

inline int qr(){
    char ch;
    while((ch=getchar())<'0'||ch>'9');
    int res=ch^48;
    while((ch=getchar())>='0'&&ch<='9')
        res=res*10+(ch^48);
    return res;
}

inline int max(int x,int y){return x<y?y:x;}
inline int min(int x,int y){return x<y?x:y;}
inline int minn(int x,int y,int z){return x<y?(x<z?x:z):(y<z?y:z);}
inline int get(int x){return x==a[x]?x:a[x]=get(a[x]);}

inline void qw(int x){
    printf("(%d %d)",(x%n==0?x/n-1:x/n),(x%n==0?n:x%n));
}

inline void yu(){
    int i=0,x,y,v;
    while(++i<=tt){
        x=t[i].x;y=t[i].y;v=t[i].v;
        if(!k[x+1][y+1]&&x+1<=n&&y+1<=n) s[x+1][y+1]=v, k[x+1][y+1]=1, t[++tt]=pi{x+1,y+1,v+1};
        if(!k[x+1][y]&&x+1<=n&&y<=n)     s[x+1][y]=v,   k[x+1][y]=1,   t[++tt]=pi{x+1,y,v+1};
        if(!k[x+1][y-1]&&x+1<=n&&0<y-1)  s[x+1][y-1]=v, k[x+1][y-1]=1, t[++tt]=pi{x+1,y-1,v+1};
        if(!k[x][y+1]&&0<x&&y+1<=n)      s[x][y+1]=v,   k[x][y+1]=1,   t[++tt]=pi{x,y+1,v+1};
        if(!k[x][y-1]&&0<x&&0<y-1)       s[x][y-1]=v,   k[x][y-1]=1,   t[++tt]=pi{x,y-1,v+1};
        if(!k[x-1][y+1]&&0<x-1&&y+1<=n)  s[x-1][y+1]=v, k[x-1][y+1]=1, t[++tt]=pi{x-1,y+1,v+1};
        if(!k[x-1][y]&&0<x-1&&y<=n)      s[x-1][y]=v,   k[x-1][y]=1,   t[++tt]=pi{x-1,y,v+1};
        if(!k[x-1][y-1]&&0<x-1&&0<y-1)   s[x-1][y-1]=v, k[x-1][y-1]=1, t[++tt]=pi{x-1,y-1,v+1};
    }
}

inline bool dfs(int i,int fa,int dp){
    for(rg j=tou[i];j;j=d[j].next){
        int to=d[j].to;
        if(to==fa)continue;
        //qw(i);cout<<"=>";qw(to);;
        if(to==yy){
            ans=min(dp,d[j].v);
            return 1;
        }
        if(dfs(to,i,min(dp,d[j].v)))return 1;
    }return 0;
}

inline void lca(int x,int dep){
    dp[x]=dep; vis[x]=1;
    for(rg i=0;i<19;++i)
        f[x][i+1]=f[f[x][i]][i];
    for(rg i=0;i<19;++i)
        st[x][i+1]=min(st[x][i],st[f[x][i]][i]);
    for(rg i=tou[x];i;i=d[i].next){
        int to=d[i].to;
        if(to==x||vis[to])continue;
        f[to][0]=x;
        st[to][0]=d[i].v;
        lca(to,dep+1);
    }
}

inline int find(int x,int y){
    if(dp[x]<dp[y])swap(x,y);
    ans=100001;
    for(rg i=19;i>=0;--i){
        if(dp[f[x][i]]>=dp[y]){
            ans=min(st[x][i],ans);
            x=f[x][i];
        }
        if(x==y)return ans;
    }
    for(rg i=19;i>=0;--i){
        if(f[x][i]!=f[y][i]){
            ans=minn(ans,st[x][i],st[y][i]);
            x=f[x][i];y=f[y][i];
        }
    }
    return minn(ans,st[x][0],st[y][0]);
}

int main(){
    //freopen("B.in","r",stdin);
    //freopen("B.out","w",stdout);
    n=qr();
    for(rg i=1;i<=n;++i){
        scanf("%s",c+1);
        for(rg j=1;j<=n;++j)
            if(c[j]!='.')k[i][j]=1,t[++tt]=pi{i,j,1};
    }
    for(rg i=0;i<=n+1;++i){
        k[i][0]=1;t[++tt]=pi{i,0,1};
        k[i][n+1]=1;t[++tt]=pi{i,n+1,1};
        k[0][i]=1;t[++tt]=pi{0,i,1};
        k[n+1][i]=1;t[++tt]=pi{n+1,i,1};
    }yu();
    for(rg i=1;i<=n;++i)
        for(rg j=1;j<n;++j)
            b[++top]=su{i*n+j-n,i*n+j+1-n,min(s[i][j],s[i][j+1])};
    for(rg i=1;i<n;++i)
        for(rg j=1;j<=n;++j)
            b[++top]=su{i*n+j-n,i*n+j,min(s[i][j],s[i+1][j])};
    sort(b+1,b+top+1);
    for(rg i=1;i<=n*n;++i)a[i]=i;
    for(rg i=1;i<=top;++i){
        if(get(b[i].x)!=get(b[i].y)){
            a[get(b[i].x)]=get(b[i].y);
            d[++ttt]=ya{b[i].y,b[i].v,tou[b[i].x]};tou[b[i].x]=ttt;
            d[++ttt]=ya{b[i].x,b[i].v,tou[b[i].y]};tou[b[i].y]=ttt;
        }
    }
    m=qr(); lca(1,1);
    for(rg i=1;i<=m;++i){
        xx=qr()*n+qr()-n; yy=qr()*n+qr()-n;
        int ans=find(xx,yy);
        printf("%d\n",(!ans?0:ans*2-1));
    }
    return 0;
}


posted @ 2019-03-05 20:11  一只不咕鸟  阅读(277)  评论(0编辑  收藏  举报