← 返回题目页

T0959 空档

标程

#include <bits/stdc++.h>
using namespace std;

using ll = long long;

struct Block {
    ll lA, rA, lB, rB;
};

// floor(sqrt(v))
ll isqrtFloor(ll v) {
    ll r = (ll)sqrtl((long double)v);
    while ((r + 1) * (r + 1) <= v) r++;
    while (r > 0 && r * r > v) r--;
    return r;
}

// 空档 [p1,p2] x [q1,q2] 里的最小代价
ll gapCost(ll p1, ll p2, ll q1, ll q2, ll X, ll Y) {
    // 对固定的 q,|X-p| + floor(sqrt(p^2+q^2)) 在 p <= X 时随 p 单调不增、p >= X 时单调不减,
    // 所以最优的 p 就是把 X 夹进区间里;q 同理。
    ll p = X < p1 ? p1 : (X > p2 ? p2 : X);
    ll q = Y < q1 ? q1 : (Y > q2 ? q2 : Y);
    return llabs(X - p) + llabs(Y - q) + isqrtFloor(p * p + q * q);
}

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

    int N, T;
    ll M;
    cin >> N >> T >> M;
    ll X, Y;
    cin >> X >> Y;

    vector<array<ll, 3>> rec(N);
    for (auto &r : rec) cin >> r[0] >> r[1] >> r[2];

    vector<vector<int>> at(T);
    for (int i = 0; i < N; i++) at[(int)rec[i][0]].push_back(i);

    // 按 A 表顺序排列的限制块
    map<ll, Block> blocks;
    blocks[0] = {0, 0, 0, 0};
    blocks[M] = {M, M, M, M};

    // 所有相邻限制块之间的空档代价
    multiset<ll> costs;
    costs.insert(gapCost(0, M, 0, M, X, Y));

    auto costOf = [&](const Block &l, const Block &r) {
        return gapCost(l.rA, r.lA, l.rB, r.lB, X, Y);
    };
    auto eraseCost = [&](ll c) {
        auto it = costs.find(c);
        if (it != costs.end()) costs.erase(it);
    };
    auto compatible = [](const Block &l, const Block &r) {
        return l.rA <= r.lA && l.rB <= r.lB;
    };

    // 把相邻的左右两个限制块合并成一个
    auto mergeRight = [&](map<ll, Block>::iterator lit, map<ll, Block>::iterator rit) {
        auto pit = (lit == blocks.begin() ? blocks.end() : prev(lit));
        auto nit = next(rit);
        if (pit != blocks.end()) eraseCost(costOf(pit->second, lit->second));
        eraseCost(costOf(lit->second, rit->second));
        if (nit != blocks.end()) eraseCost(costOf(rit->second, nit->second));

        lit->second.rA = rit->second.rA;
        lit->second.lB = min(lit->second.lB, rit->second.lB);
        lit->second.rB = max(lit->second.rB, rit->second.rB);
        blocks.erase(rit);

        if (pit != blocks.end()) costs.insert(costOf(pit->second, lit->second));
        if (nit != blocks.end()) costs.insert(costOf(lit->second, nit->second));
    };

    // 反复合并,直到所有相邻限制块都能保持分离
    auto stabilize = [&](map<ll, Block>::iterator it) {
        bool changed = true;
        while (changed) {
            changed = false;
            while (true) {
                auto rit = next(it);
                if (rit == blocks.end() || compatible(it->second, rit->second)) break;
                mergeRight(it, rit);
                changed = true;
            }
            while (true) {
                if (it == blocks.begin()) break;
                auto lit = prev(it);
                if (compatible(lit->second, it->second)) break;
                mergeRight(lit, it);
                it = lit;
                changed = true;
            }
        }
    };

    for (int t = 0; t < T; t++) {
        for (int id : at[t]) {
            ll a = rec[id][1], b = rec[id][2];
            Block nb = {a, a, b, b};
            auto rit = blocks.upper_bound(a);
            auto lit = (rit == blocks.begin() ? blocks.end() : prev(rit));
            if (lit != blocks.end() && rit != blocks.end()) {
                eraseCost(costOf(lit->second, rit->second));
            }
            auto nit = blocks.insert({a, nb}).first;
            if (lit != blocks.end()) costs.insert(costOf(lit->second, nit->second));
            if (rit != blocks.end()) costs.insert(costOf(nit->second, rit->second));
            stabilize(nit);
        }
        cout << *costs.begin() << "\n";
    }
    return 0;
}

动画演示