Codeforces Gym 101173 H. Hangar Hurdles (LCA + and Collection)

meaning of the title

A rectangular N * N map composed of. and #. k I j denotes that the edge length of the largest square centered on (i, j) is k.

For each query from (sx, sy) to (ex, ey), the maximum square edge length k makes it possible to satisfy that there is no

Solving problems

Firstly, the k of each point is solved by flooding algorithm. See flood_fill().

When enumerating point i, it expands in four directions. If point j has been visited, it finds the ancestor node AJ of the same set, links it from I to aj, and combines I through and checks the set.

For each group of questions, the k value of the ancestor point is the maximum value of the answer when the nearest common ancestor is obtained by LCA.

Code

#include<bits/stdc++.h>
using namespace std;
const int N = 1000 + 10;
const int dir[8][2] = {-1,0, 1,0, 0,-1, 0,1, -1,-1, -1,1, 1,-1, 1,1};
int n, q, k[N][N], vis[N][N];
char flr[N][N];
pair<int, int> arr[N*N];
bool cmp(pair<int, int> a, pair<int, int> b) {
    return a.second > b.second;
}

struct Edge {
    int nxt, to;
} e[N*N*2];
int head[N*N], cnt;
void addedge(int u, int v) {
    e[++cnt].nxt = head[u];
    e[cnt].to = v;
    head[u] = cnt;
}

int fa[N*N];
int find(int x)  {   return fa[x] = fa[x] == x ? x : find(fa[x]);    }

void flood_fill()
{
    queue<pair<int, int> > que;
    pair<int, int> p, q;
    memset(k, 0x3f, sizeof(k));
    for(int i=0;i<=n+1;i++)
    for(int j=0;j<=n+1;j++)
        if(flr[i][j] == '#' || i==0 || i==n+1 || j==0 || j==n+1)
            que.push(make_pair(i, j)),  k[i][j] = -1;
    while(!que.empty())
    {
        p = que.front();
        que.pop();
        for(int i=0;i<8;i++)
        {
            q = make_pair(p.first+dir[i][0], p.second+dir[i][1]);
            if(q.first<=0 || q.first>n || q.second<=0 || q.second>n || k[q.first][q.second] != 0x3f3f3f3f)  continue;
            k[q.first][q.second] = k[p.first][p.second] + 2;
            que.push(q);
        }
        if(k[p.first][p.second] == -1)  k[p.first][p.second] = 0;
    }
}

void solve(int r, int c)
{
    vis[r][c] = 1;
    for(int i=0, nr, nc;i<4;i++)
    {
        nr = r + dir[i][0];
        nc = c + dir[i][1];
        if(nr<=0 || nr>n || nc<=0 || nc>n || vis[nr][nc] == 0)  continue;
        int x = find((nr-1)*n+nc-1);
        int y = find((r-1)*n+c-1);
        if(x == y)  continue;
        fa[x] = y;
        addedge(y, x);  addedge(x, y);
    }
}

const int maxh = 20;
int dep[N*N];
int anc[N*N][20];
void dfs(int rt) {
    static int Stack[N*N];
    int top = 0;
    dep[rt] = 1;
    for(int i=0;i<maxh;i++)
        anc[rt][i] = rt;
    Stack[++top] = rt;
    while(top) {
        int x = Stack[top];
        if(x != rt) {
            for(int i=1, y;i<maxh;i++)
                y = anc[x][i-1],    anc[x][i] = anc[y][i-1];
        }
        for(int &i=head[x];i;i=e[i].nxt) {
            int y = e[i].to;
            if(y != anc[x][0]) {
                dep[y] = dep[x] + 1;
                anc[y][0] = x;
                Stack[++top] = y;
            }
        }
        while(top && head[Stack[top]] == 0) top--;
    }
}
void swim(int &x, int H) {
    for(int i=0;H;i++) {
        if(H & 1)   x = anc[x][i];
        H /= 2;
    }
}
int lca(int x, int y) {
    int i;
    if(dep[x] > dep[y]) swap(x, y);
    swim(y, dep[y]-dep[x]);
    if(x == y)  return x;
    for(;;) {
        for(i=0;anc[x][i] != anc[y][i];i++);
        if(i == 0)  return anc[x][0];
        x = anc[x][i-1];
        y = anc[y][i-1];
    }
    return -1;
}

int main()
{
    while(scanf("%d", &n)!=EOF)
    {
        for(int i=1;i<=n;i++)
            scanf(" %s", flr[i]+1);
        // Calculate the maximum k of each point.
        flood_fill();

        for(int i=1, x;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            x = (i-1)*n+j-1;
            arr[x].first = x;
            arr[x].second = k[i][j];
        }
        sort(arr, arr+n*n, cmp);

        for(int i=0;i<=n*n;i++)
            fa[i] = i;
        memset(vis, 0, sizeof(vis));
        for(int i=0, x;i<n*n;i++) {
            x = arr[i].first;
            solve(x/n+1, x%n+1);
        }
        dfs(arr[n*n-1].first);

        scanf("%d", &q);
        for(int i=0, sx, sy, ex, ey;i<q;i++)
        {
            scanf("%d %d %d %d", &sx, &sy, &ex, &ey);
            int pointIdx = lca((sx-1)*n+sy-1, (ex-1)*n+ey-1);
            printf("%d\n", k[pointIdx/n+1][pointIdx%n+1]);
        }
    }
}

Posted by cbailster on Tue, 12 Feb 2019 21:57:21 -0800