OI XXIII - par

// https://szkopul.edu.pl/problemset/problem/70I-ks8dXjgq3xwzRzLV1w4p/site/?key=statement

#include <bits/stdc++.h>

using namespace std;

#define int long long

constexpr int sizik = 1006;

#define ar std::array
#define pr std::pair
#define vec std::vector

// #define GARY_DBG

typedef vec<vec<int>> _kra;

constexpr ar<int, 4> dx = {0, 1, 0, -1};
constexpr ar<int, 4> dy = {1, 0, -1, 0};

int n;
int ans;

// [y][x]
char mapx[sizik][sizik];

bool visited[sizik][sizik];
int curr_num = 1;
int numer_spojnej[sizik][sizik];
// std::vector<int> rozmiar_spojnej;
int rozmiar_spojnej[sizik * sizik];
// vector<pair<int, int>> pairs;
int max_spojna = 0;

void DFS(int y, int x) {
    if (visited[y][x]) return;
    visited[y][x] = true;
    numer_spojnej[y][x] = curr_num;
    max_spojna = std::max(max_spojna, ++rozmiar_spojnej[curr_num]);
    for (int dir = 0; dir < 4; dir++) {
        int nx = x + dx[dir];
        int ny = y + dy[dir];
        if (mapx[ny][nx] == 'B') {
            DFS(ny, nx);
        }
    }
}

std::vector<int> zkim_sasiaduje_ar[sizik][sizik];

std::vector<int> zkim_sasiaduje(int x, int y) {
    std::vector<int> xd;
    for (int dir = 0; dir < 4; dir++) {
        int nx = x + dx[dir];
        int ny = y + dy[dir];
        if (mapx[ny][nx] == 'B') {
            xd.push_back(numer_spojnej[ny][nx]);
        }
    }
    return xd;
}

std::vector<int> combineUnique(const std::vector<int>& a, const std::vector<int>& b) {
    std::unordered_set<int> seen;
    std::vector<int> result;

    for (int x : a)
        if (seen.insert(x).second) result.push_back(x);

    for (int x : b)
        if (seen.insert(x).second) result.push_back(x);

    return result;
}

void makeUnique(std::vector<int>& v1) {
    std::unordered_set<int> uniqueElements(v1.begin(), v1.end());

    v1.clear();

    for (int val : uniqueElements) {
        v1.push_back(val);
    }
}

int combine_ans(const std::vector<int>& yui, int x, int y) {
    const auto& zui = zkim_sasiaduje_ar[x][y];
    auto xui = combineUnique(yui, zui);
    int ansix = 2;
    for (const auto& xik : xui) {
        ansix += rozmiar_spojnej[xik];
    }
    return ansix;
}

ar<ar<ar<int, 2>, 2>, sizik * sizik> rogi;

void wyznacz_prostokaty() {
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            if (mapx[i][j] == 'B') {
                rogi[numer_spojnej[i][j]][1] = {j, i};
                const auto& [x, y] = rogi[numer_spojnej[i][j]][0];
                if (x == 0 && y == 0) {
                    rogi[numer_spojnej[i][j]][0] = {j, i};
                }
            }
        }
    }
}

bool try_add_aisle(vector<vector<int>>& curAisles, const vector<int>& nextAisle, int curPool) {
    for (auto& other : curAisles) {
        if (includes(other.begin(), other.end(), nextAisle.begin(), nextAisle.end())) {
            return false;
        }
    }
    vector<int> addedAisle;
    for (int v : nextAisle)
        if (v != curPool) addedAisle.push_back(v);
    curAisles.push_back(addedAisle);
    return true;
}

int get_total_area(const vector<int>& pools) {
    int result = 0;
    for (int pool : pools)
        result += rozmiar_spojnej[pool];
    return result;
}

void main_loop() {
    for (int idxsp = 2; idxsp < (int)rogi.size(); idxsp++) {
        const auto& a = rogi[idxsp];
        if (a[0][0] == 0) break;

        std::vector<std::vector<int>> singleAisles, multAisles;

        for (int p = a[0][0]; p <= a[1][0]; p++) {
            for (int q = 0, add = -1; q <= 1; q++, add += 2) {
                const std::vector<int>& neighbors = zkim_sasiaduje_ar[p][a[q][1] + add];
                if (neighbors.size() == 1) continue;
                (neighbors.size() == 2 ? singleAisles : multAisles).push_back(neighbors);
            }
        }

        for (int p = a[0][1]; p <= a[1][1]; p++) {
            for (int q = 0, add = -1; q <= 1; q++, add += 2) {
                const std::vector<int>& neighbors = zkim_sasiaduje_ar[a[q][0] + add][p];
                if (neighbors.size() == 1) continue;
                (neighbors.size() == 2 ? singleAisles : multAisles).push_back(neighbors);
            }
        }

        vector<vector<int>> feasibleAisles;

        for (auto& aisle : multAisles)
            try_add_aisle(feasibleAisles, aisle, idxsp);

        vector<int> singleAlone;
        for (auto& single : singleAisles) {
            int v = (single[0] == idxsp ? single[1] : single[0]);
            bool okay = true;
            for (auto& mult : feasibleAisles) {
                if (find(mult.begin(), mult.end(), v) != mult.end()) {
                    okay = false;
                    break;
                }
            }

            if (okay) singleAlone.push_back(v);
        }

        int best1 = -1, best2 = -1;
        for (int v : singleAlone) {
            if (v == best1 || v == best2) continue;

            if (best1 == -1 || rozmiar_spojnej[best1] < rozmiar_spojnej[v]) {
                best2 = best1;
                best1 = v;
            } else if (best2 == -1 || rozmiar_spojnej[best2] < rozmiar_spojnej[v]) {
                best2 = v;
            }
        }
        if (best1 != -1) feasibleAisles.push_back({best1});
        if (best2 != -1) feasibleAisles.push_back({best2});

        int S = (int)feasibleAisles.size();
        int result = 2 + rozmiar_spojnej[idxsp];
        for (int fst = 0; fst < S; fst++) {
            result = std::max(result, 2ll + rozmiar_spojnej[idxsp] + get_total_area(feasibleAisles[fst]));

            for (int snd = fst + 1; snd < S; snd++) {
                vector<int>&A1 = feasibleAisles[fst], A2 = feasibleAisles[snd];
                vector<int> everything;
                set_union(A1.begin(), A1.end(), A2.begin(), A2.end(), back_inserter(everything));
                result = max(result, 2 + rozmiar_spojnej[idxsp] + get_total_area(everything));
            }
        }

        ans = std::max(ans, result);
    }
}

int32_t main() {
    std::ios_base::sync_with_stdio(0);
    std::cin.tie(0);
    std::cout.tie(0);

    std::cin >> n;

    int o = 0;

    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            std::cin >> mapx[i][j];
            if (mapx[i][j] == 'A') {
                o++;
            }
        }
    }

    if (o == 0 || o == 1 || o == 2) {
        std::cout << n * n << '\n';
        return 0;
    }

    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            if (!visited[i][j] && mapx[i][j] == 'B') {
                curr_num++;
                DFS(i, j);
            }
        }
    }

    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            zkim_sasiaduje_ar[j][i] = zkim_sasiaduje(j, i);
            std::sort(zkim_sasiaduje_ar[j][i].begin(), zkim_sasiaduje_ar[j][i].end());
        }
    }

    ans = max_spojna + 2;

    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            // mapx[i][j]
            if (mapx[i][j] != 'A') continue;

            auto yui = zkim_sasiaduje_ar[j][i];

            if (mapx[i][j + 1] == 'A') {
                int ansix = combine_ans(yui, j + 1, i);
                ans = std::max(ans, ansix);
            }
            if (mapx[i + 1][j] == 'A') {
                int ansix = combine_ans(yui, j, i + 1);
                ans = std::max(ans, ansix);
            }
        }
    }

    wyznacz_prostokaty();
    main_loop();

    std::cout << ans << '\n';
}