AC Code For CF1681E

AC Code For CF1681E

#include <bits/stdc++.h>

typedef long long valueType;
typedef std::vector<valueType> ValueVector;
typedef std::vector<ValueVector> ValueMatrix;
typedef std::vector<ValueMatrix> ValueCube;
typedef std::pair<valueType, valueType> ValuePair;
typedef std::vector<ValuePair> PairVector;
typedef std::array<std::array<ValueMatrix, 2>, 2> MatrixArray;
typedef std::array<std::array<ValueCube, 2>, 2> CubeArray;

valueType N, M, Block, K;
ValueVector leftBound, rightBound, belong;
PairVector upDoor, rightDoor;
MatrixArray distS;
CubeArray distN;

constexpr valueType MAX = LONG_LONG_MAX >> 2;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);

    std::cin >> N;

    Block = std::ceil(std::pow(N, (long double) 1 / 3));
    K = std::ceil((long double) N / Block);

    leftBound.resize(K + 1, 0);
    rightBound.resize(K + 1, 0);
    belong.resize(N + 1, 0);
    upDoor.resize(N + 1);
    rightDoor.resize(N + 1);
    distS[0][0].resize(K + 1, ValueVector(K + 1, MAX));
    distS[0][1].resize(K + 1, ValueVector(K + 1, MAX));
    distS[1][0].resize(K + 1, ValueVector(K + 1, MAX));
    distS[1][1].resize(K + 1, ValueVector(K + 1, MAX));
    distN[0][0].resize(K + 1, ValueMatrix(Block + 1, ValueVector(Block + 1, MAX)));
    distN[0][1].resize(K + 1, ValueMatrix(Block + 1, ValueVector(Block + 1, MAX)));
    distN[1][0].resize(K + 1, ValueMatrix(Block + 1, ValueVector(Block + 1, MAX)));
    distN[1][1].resize(K + 1, ValueMatrix(Block + 1, ValueVector(Block + 1, MAX)));

    for (valueType i = 1; i < N; ++i) {
        std::cin >> upDoor[i].second >> upDoor[i].first >> rightDoor[i].second >> rightDoor[i].first;

        belong[i] = (i - 1) / Block + 1;
    }

    belong[N] = K;

    for (valueType i = 1; i < K; ++i) {
        leftBound[i] = (i - 1) * Block + 1;
        rightBound[i] = i * Block + 1;
    }

    leftBound[K] = (K - 1) * Block + 1;
    rightBound[K] = N;

    for (valueType i = 1; i <= K; ++i) {
        valueType const offset = leftBound[i];

        for (valueType j = leftBound[i]; j <= rightBound[i]; ++j) {
            distN[0][0][i][j - offset][j - offset] = 0;
            distN[0][1][i][j - offset][j - offset] = j - upDoor[j - 1].first + j - rightDoor[j - 1].second;
            distN[1][0][i][j - offset][j - offset] = j - upDoor[j - 1].first + j - rightDoor[j - 1].second;
            distN[1][1][i][j - offset][j - offset] = 0;
        }

        for (valueType j = leftBound[i]; j < rightBound[i]; ++j) {
            distN[0][0][i][j - offset][j + 1 - offset] = 1 + std::abs(upDoor[j].first - upDoor[j - 1].first);
            distN[1][1][i][j - offset][j + 1 - offset] = 1 + std::abs(rightDoor[j].second - rightDoor[j - 1].second);
            distN[1][0][i][j - offset][j + 1 - offset] = 1 + j - rightDoor[j - 1].second + j - upDoor[j].first;
            distN[0][1][i][j - offset][j + 1 - offset] = 1 + j - upDoor[j - 1].first + j - rightDoor[j].second;
        }

        for (valueType len = 2; len <= rightBound[i] - leftBound[i]; ++len) {
            for (valueType l = leftBound[i]; l + len <= rightBound[i]; ++l) {
                valueType const r = l + len;

                distN[0][0][i][l - offset][r - offset] = std::min(
                        distN[0][0][i][l - offset][r - 1 - offset] + distN[0][0][i][r - 1 - offset][r - offset],
                        distN[0][1][i][l - offset][r - 1 - offset] + distN[1][0][i][r - 1 - offset][r - offset]);

                distN[0][1][i][l - offset][r - offset] = std::min(
                        distN[0][0][i][l - offset][r - 1 - offset] + distN[0][1][i][r - 1 - offset][r - offset],
                        distN[0][1][i][l - offset][r - 1 - offset] + distN[1][1][i][r - 1 - offset][r - offset]);

                distN[1][0][i][l - offset][r - offset] = std::min(
                        distN[1][0][i][l - offset][r - 1 - offset] + distN[0][0][i][r - 1 - offset][r - offset],
                        distN[1][1][i][l - offset][r - 1 - offset] + distN[1][0][i][r - 1 - offset][r - offset]);

                distN[1][1][i][l - offset][r - offset] = std::min(
                        distN[1][0][i][l - offset][r - 1 - offset] + distN[0][1][i][r - 1 - offset][r - offset],
                        distN[1][1][i][l - offset][r - 1 - offset] + distN[1][1][i][r - 1 - offset][r - offset]);
            }
        }

        distS[0][0][i][i] = distN[0][0][i][0][rightBound[i] - offset];
        distS[0][1][i][i] = distN[0][1][i][0][rightBound[i] - offset];
        distS[1][0][i][i] = distN[1][0][i][0][rightBound[i] - offset];
        distS[1][1][i][i] = distN[1][1][i][0][rightBound[i] - offset];
    }

    for (valueType len = 1; len < K; ++len) {
        for (valueType l = 1; l + len <= K; ++l) {
            valueType const r = l + len;

            distS[0][0][l][r] = std::min(distS[0][0][l][r - 1] + distS[0][0][r][r],
                                         distS[0][1][l][r - 1] + distS[1][0][r][r]);

            distS[0][1][l][r] = std::min(distS[0][0][l][r - 1] + distS[0][1][r][r],
                                         distS[0][1][l][r - 1] + distS[1][1][r][r]);

            distS[1][0][l][r] = std::min(distS[1][0][l][r - 1] + distS[0][0][r][r],
                                         distS[1][1][l][r - 1] + distS[1][0][r][r]);

            distS[1][1][l][r] = std::min(distS[1][0][l][r - 1] + distS[0][1][r][r],
                                         distS[1][1][l][r - 1] + distS[1][1][r][r]);
        }
    }

    std::cin >> M;

    for (valueType m = 0; m < M; ++m) {
        valueType x1, y1, x2, y2;

        std::cin >> y1 >> x1 >> y2 >> x2;

        if (x1 == x2 && y1 == y2) {
            std::cout << 0 << '\n';

            continue;
        }

        valueType l = std::max(x1, y1), r = std::max(x2, y2);

        if (l > r) {
            std::swap(l, r);
            std::swap(x1, x2);
            std::swap(y1, y2);
        }

        if (l == r) {
            if (x1 == l) {
                if (x2 == l) {
                    std::cout << std::abs(y1 - y2) << '\n';
                } else {
                    std::cout << l - x2 + l - y1 << '\n';
                }
            } else {
                if (x2 == l) {
                    std::cout << l - x1 + l - y2 << '\n';
                } else {
                    std::cout << std::abs(x1 - x2) << '\n';
                }
            }

            continue;
        } else if (l + 1 == r) {
            valueType ans = MAX;

            { // case 0
                valueType base = 1;

                if (x1 == l) {
                    base += l - y1;
                    base += l - upDoor[l].first;
                } else {
                    base += std::abs(x1 - upDoor[l].first);
                }

                if (x2 == r) {
                    base += r - y2;
                    base += r - upDoor[l].first;
                } else {
                    base += std::abs(x2 - upDoor[l].first);
                }

                ans = std::min(ans, base);
            }

            { //case 1
                valueType base = 1;

                if (y1 == l) {
                    base += l - x1;
                    base += l - rightDoor[l].second;
                } else {
                    base += std::abs(y1 - rightDoor[l].second);
                }

                if (y2 == r) {
                    base += r - x2;
                    base += r - rightDoor[l].second;
                } else {
                    base += std::abs(y2 - rightDoor[l].second);
                }

                ans = std::min(ans, base);
            }

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

            continue;
        }

        ++l;

        valueType const left = belong[l], right = belong[r];

        valueType const leftOffset = leftBound[left], rightOffset = leftBound[right];

        valueType const rightTo = rightBound[left] - leftOffset;

        valueType ans = MAX;

        { //case 0 - 0
            valueType base = 0;

            if (x1 == l - 1) {
                base += l - 1 - y1;
                base += l - 1 - upDoor[l - 1].first;
            } else {
                base += std::abs(x1 - upDoor[l - 1].first);
            }

            if (x2 == r) {
                base += r - y2;
                base += r - upDoor[r - 1].first;
            } else {
                base += std::abs(x2 - upDoor[r - 1].first);
            }

            valueType min = MAX;

            if (left == right) {
                min = distN[0][0][left][l - leftOffset][r - rightOffset];
            } else if (left + 1 == right) {
                min = std::min(min,
                               distN[0][0][left][l - leftOffset][rightTo] + distN[0][0][right][0][r - rightOffset]);
                min = std::min(min,
                               distN[0][1][left][l - leftOffset][rightTo] + distN[1][0][right][0][r - rightOffset]);
            } else {
                min = std::min(min, distN[0][0][left][l - leftOffset][rightTo] + distS[0][0][left + 1][right - 1] +
                                    distN[0][0][right][0][r - rightOffset]);

                min = std::min(min, distN[0][0][left][l - leftOffset][rightTo] + distS[0][1][left + 1][right - 1] +
                                    distN[1][0][right][0][r - rightOffset]);

                min = std::min(min, distN[0][1][left][l - leftOffset][rightTo] + distS[1][0][left + 1][right - 1] +
                                    distN[0][0][right][0][r - rightOffset]);

                min = std::min(min, distN[0][1][left][l - leftOffset][rightTo] + distS[1][1][left + 1][right - 1] +
                                    distN[1][0][right][0][r - rightOffset]);
            }

            ans = std::min(ans, min + base);
        }

        { //case 0 - 1
            valueType base = 0;

            if (x1 == l - 1) {
                base += l - 1 - y1;
                base += l - 1 - upDoor[l - 1].first;
            } else {
                base += std::abs(x1 - upDoor[l - 1].first);
            }

            if (y2 == r) {
                base += r - x2;
                base += r - rightDoor[r - 1].second;
            } else {
                base += std::abs(y2 - rightDoor[r - 1].second);
            }

            valueType min = MAX;

            if (left == right) {
                min = distN[0][1][left][l - leftOffset][r - rightOffset];
            } else if (left + 1 == right) {
                min = std::min(min,
                               distN[0][0][left][l - leftOffset][rightTo] + distN[0][1][right][0][r - rightOffset]);
                min = std::min(min,
                               distN[0][1][left][l - leftOffset][rightTo] + distN[1][1][right][0][r - rightOffset]);
            } else {
                min = std::min(min, distN[0][0][left][l - leftOffset][rightTo] + distS[0][0][left + 1][right - 1] +
                                    distN[0][1][right][0][r - rightOffset]);

                min = std::min(min, distN[0][0][left][l - leftOffset][rightTo] + distS[0][1][left + 1][right - 1] +
                                    distN[1][1][right][0][r - rightOffset]);

                min = std::min(min, distN[0][1][left][l - leftOffset][rightTo] + distS[1][0][left + 1][right - 1] +
                                    distN[0][1][right][0][r - rightOffset]);

                min = std::min(min, distN[0][1][left][l - leftOffset][rightTo] + distS[1][1][left + 1][right - 1] +
                                    distN[1][1][right][0][r - rightOffset]);
            }

            ans = std::min(ans, min + base);
        }

        { //case 1 - 0
            valueType base = 0;

            if (y1 == l - 1) {
                base += l - 1 - x1;
                base += l - 1 - rightDoor[l - 1].second;
            } else {
                base += std::abs(y1 - rightDoor[l - 1].second);
            }

            if (x2 == r) {
                base += r - y2;
                base += r - upDoor[r - 1].first;
            } else {
                base += std::abs(x2 - upDoor[r - 1].first);
            }

            valueType min = MAX;

            if (left == right) {
                min = distN[1][0][left][l - leftOffset][r - rightOffset];
            } else if (left + 1 == right) {
                min = std::min(min,
                               distN[1][0][left][l - leftOffset][rightTo] + distN[0][0][right][0][r - rightOffset]);
                min = std::min(min,
                               distN[1][1][left][l - leftOffset][rightTo] + distN[1][0][right][0][r - rightOffset]);
            } else {
                min = std::min(min, distN[1][0][left][l - leftOffset][rightTo] + distS[0][0][left + 1][right - 1] +
                                    distN[0][0][right][0][r - rightOffset]);

                min = std::min(min, distN[1][0][left][l - leftOffset][rightTo] + distS[0][1][left + 1][right - 1] +
                                    distN[1][0][right][0][r - rightOffset]);

                min = std::min(min, distN[1][1][left][l - leftOffset][rightTo] + distS[1][0][left + 1][right - 1] +
                                    distN[0][0][right][0][r - rightOffset]);

                min = std::min(min, distN[1][1][left][l - leftOffset][rightTo] + distS[1][1][left + 1][right - 1] +
                                    distN[1][0][right][0][r - rightOffset]);
            }

            ans = std::min(ans, min + base);
        }

        { //case 1 - 1
            valueType base = 0;

            if (y1 == l - 1) {
                base += l - 1 - x1;
                base += l - 1 - rightDoor[l - 1].second;
            } else {
                base += std::abs(y1 - rightDoor[l - 1].second);
            }

            if (y2 == r) {
                base += r - x2;
                base += r - rightDoor[r - 1].second;
            } else {
                base += std::abs(y2 - rightDoor[r - 1].second);
            }

            valueType min = MAX;

            if (left == right) {
                min = distN[1][1][left][l - leftOffset][r - rightOffset];
            } else if (left + 1 == right) {
                min = std::min(min,
                               distN[1][0][left][l - leftOffset][rightTo] + distN[0][1][right][0][r - rightOffset]);
                min = std::min(min,
                               distN[1][1][left][l - leftOffset][rightTo] + distN[1][1][right][0][r - rightOffset]);
            } else {
                min = std::min(min, distN[1][0][left][l - leftOffset][rightTo] + distS[0][0][left + 1][right - 1] +
                                    distN[0][1][right][0][r - rightOffset]);

                min = std::min(min, distN[1][0][left][l - leftOffset][rightTo] + distS[0][1][left + 1][right - 1] +
                                    distN[1][1][right][0][r - rightOffset]);

                min = std::min(min, distN[1][1][left][l - leftOffset][rightTo] + distS[1][0][left + 1][right - 1] +
                                    distN[0][1][right][0][r - rightOffset]);

                min = std::min(min, distN[1][1][left][l - leftOffset][rightTo] + distS[1][1][left + 1][right - 1] +
                                    distN[1][1][right][0][r - rightOffset]);
            }

            ans = std::min(ans, min + base);
        }

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

    std::cout << std::flush;

    return 0;
}
posted @ 2023-08-23 17:19  User-Unauthorized  阅读(15)  评论(0编辑  收藏  举报