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;
}