Submission #1336152

#TimeUsernameProblemLanguageResultExecution timeMemory
1336152c4lBitaro, who Leaps through Time (JOI19_timeleap)C++20
0 / 100
304 ms5612 KiB
#include <bits/stdc++.h>
using namespace std;
using int64 = long long;
const int64 INF64 = (int64)4e18;

// Giả định dạng input:
// N Q
// L1 R1
// L2 R2
// ...
// L_{N-1} R_{N-1}
//
// Sau đó Q dòng:
// type ... 
// type = 1 i l r   -> cập nhật đường i (1 <= i <= N-1): L_i = l, R_i = r
// type = 2 A B C D -> truy vấn: bắt đầu ở thành phố A vào thời B, đích C vào thời D
//
// Output: với mỗi truy vấn type=2 in ra số time-leap tối thiểu (non-negative) hoặc -1 nếu không thể.

// Hàm mô phỏng: bắt đầu thời điểm t0 tại thành phố A, cố gắng đi tới C.
// Returns earliest arrival time at city C if có thể, otherwise returns INF64 (không thể).
// Chúng ta dùng quy ước: để bắt đầu băng qua đường i vào thời t (đi từ i -> i+1),
// cần t trong [L[i], R[i]-1] (vì phải dùng khoảng [t,t+1] nằm trong [L_i, R_i]).
int64 earliest_arrival(int N, int A, int C, int64 t0, const vector<int64>& L, const vector<int64>& R) {
    int64 t = t0;
    if (A == C) return t; // ở đúng chỗ, có thể đợi tới D nếu cần
    if (A < C) {
        for (int i = A; i <= C-1; ++i) {
            int64 Li = L[i];
            int64 Ri = R[i] - 1; // tối đa start time cho phép
            if (t > Ri) return INF64;          // không kịp, vì đã vượt quá thời hạn cuối cùng để bắt đầu đi qua đường này
            t = max(t, Li); // có thể đợi tới Li nếu cần
            // bây giờ t in [Li, Ri], bắt đầu đi qua -> tới thành phố tiếp theo vào t+1
            t = t + 1;
        }
        return t;
    } else {
        // đi trái: từ A -> A-1 -> ... -> C
        // đường dùng khi đi từ x -> x-1 là đường index x-1
        for (int i = A-1; i >= C; --i) {
            int64 Li = L[i];
            int64 Ri = R[i] - 1;
            if (t > Ri) return INF64;
            t = max(t, Li);
            t = t + 1;
        }
        return t;
    }
}

// Kiểm tra với k (số time-leap): có thể đạt tới (C,D) không?
bool can_with_k(int N, int A, int64 B, int C, int64 D, int64 k, const vector<int64>& L, const vector<int64>& R) {
    int64 t0 = B - k;
    int64 arrival = earliest_arrival(N, A, C, t0, L, R);
    if (arrival == INF64) return false;
    // nếu đến sớm hơn D thì có thể đợi tới D (chỉ được đợi tăng thời gian)
    return arrival <= D;
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int N, Q;
    if (!(cin >> N >> Q)) return 0;
    // N thành phố, có N-1 đường 1..N-1
    vector<int64> L(N), R(N); // we'll use indices 1..N-1, index 0 unused
    for (int i = 1; i <= N-1; ++i) {
        cin >> L[i] >> R[i];
    }

    while (Q--) {
        int type;
        cin >> type;
        if (type == 1) {
            int idx;
            int64 l, r;
            cin >> idx >> l >> r;
            // cập nhật đường idx
            L[idx] = l;
            R[idx] = r;
        } else if (type == 2) {
            int A, C;
            int64 B, D;
            cin >> A >> B >> C >> D;
            // Lower bound k: ít nhất phải có B - k <= D => k >= max(0, B-D)
            int64 lb = 0;
            if (B > D) lb = B - D;

            // Nếu A == C: không cần đi đường nào, chỉ cần đảm bảo start time <= D
            if (A == C) {
                cout << lb << '\n';
                continue;
            }

            // Exponential search để tìm high sao cho can_with_k(high) == true
            int64 hi = max<int64>(1, lb);
            // Cap hi to avoid infinite loop if impossible: cap at 4e18
            bool found = false;
            for (int iter = 0; iter < 62; ++iter) { // 62 iterations enough to cover up to ~4e18
                if (can_with_k(N, A, B, C, D, hi, L, R)) { found = true; break; }
                // tăng hi
                if (hi > (INF64 / 2)) break;
                hi = hi * 2;
            }
            if (!found) {
                // thử thêm 1 lần với một giá trị rất lớn
                if (!can_with_k(N, A, B, C, D, INF64/4, L, R)) {
                    cout << -1 << '\n';
                    continue;
                } else {
                    hi = INF64/4;
                }
            }

            // Binary search [lb, hi]
            int64 lo = lb, ans = -1;
            while (lo <= hi) {
                int64 mid = lo + (hi - lo) / 2;
                if (can_with_k(N, A, B, C, D, mid, L, R)) {
                    ans = mid;
                    hi = mid - 1;
                } else lo = mid + 1;
            }
            if (ans == -1) cout << -1 << '\n';
            else cout << ans << '\n';
        } else {
            // không hợp lệ theo giả định format
            // ta có thể bỏ qua hoặc dừng
            cerr << "Unknown query type: " << type << "\n";
            return 0;
        }
    }
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...