제출 #1310603

#제출 시각아이디문제언어결과실행 시간메모리
1310603harryleeeFire (BOI24_fire)C++20
0 / 100
1 ms716 KiB
#include <bits/stdc++.h>
using namespace std;

const int INF = 1e9;

struct Interval {
    int id;
    int l, r;
    // Để sắp xếp: ưu tiên l nhỏ nhất, nếu l bằng nhau thì r lớn nhất đứng trước
    bool operator<(const Interval& other) const {
        if (l != other.l) return l < other.l;
        return r > other.r;
    }
};

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    int n, m;
    if (!(cin >> n >> m)) return 0;

    vector<Interval> a;
    for (int i = 0; i < n; ++i) {
        int s, e;
        cin >> s >> e;
        if (s < e) {
            a.push_back({i, s, e});
            a.push_back({i, s + m, e + m});
        } else {
            // Qua đêm: ví dụ 90 -> 10 trong ngày 100 thành 90 -> 110
            a.push_back({i, s, e + m});
            a.push_back({i, s + m, e + 2 * m});
        }
    }

    // Sắp xếp các khoảng theo thời gian bắt đầu
    sort(a.begin(), a.end());

    int sz = a.size();
    
    // next_interval[i] lưu chỉ số của khoảng tốt nhất để nhảy tới từ khoảng i
    vector<int> nxt(sz);
    
    // Kỹ thuật 2 con trỏ (Two Pointers) hoặc tìm max prefix để tìm nxt[i]
    // Vì mảng đã sort theo L, với mỗi i, ta cần tìm j sao cho L[j] <= R[i] và R[j] là max.
    
    // Precompute max R cho các prefix để truy vấn nhanh
    // Tuy nhiên, chỉ cần duy trì một "cửa sổ" các interval hợp lệ.
    // Cách đơn giản hơn: Với mỗi i, ta tìm upper_bound của R[i] trong mảng L,
    // và cần max R trong đoạn [0, index_found - 1].
    
    // Xây dựng mảng max_r_index[k] lưu chỉ số của interval có R lớn nhất trong phạm vi a[0...k]
    vector<int> max_r_idx(sz);
    max_r_idx[0] = 0;
    for(int i = 1; i < sz; ++i){
        if (a[i].r > a[max_r_idx[i-1]].r) {
            max_r_idx[i] = i;
        } else {
            max_r_idx[i] = max_r_idx[i-1];
        }
    }

    // Xây dựng Binary Lifting
    // up[k][i] là chỉ số interval sau khi nhảy 2^k bước từ i
    int LOG = 20;
    vector<vector<int>> up(LOG, vector<int>(sz));

    // Tìm điểm đến trực tiếp (bước nhảy 2^0)
    for (int i = 0; i < sz; ++i) {
        // Tìm khoảng j xa nhất về bên phải mà a[j].l <= a[i].r
        // Sử dụng binary search trên l
        Interval key; 
        key.l = a[i].r; 
        key.r = 2000000000; // Để đảm bảo upper_bound trả về phần tử đầu tiên > a[i].r
        
        auto it = upper_bound(a.begin(), a.end(), key);
        int idx = distance(a.begin(), it) - 1;

        if (idx == -1) {
            // Không có khoảng nào bắt đầu trước khi i kết thúc (trường hợp này khó xảy ra nếu sort đúng và dữ liệu hợp lệ)
            up[0][i] = i; 
        } else {
            int best_idx = max_r_idx[idx];
            // Nếu khoảng tốt nhất không giúp vươn xa hơn hiện tại, ta bị kẹt
            if (a[best_idx].r <= a[i].r) {
                up[0][i] = i;
            } else {
                up[0][i] = best_idx;
            }
        }
    }

    // Xây dựng các bước nhảy lớn hơn
    for (int k = 1; k < LOG; ++k) {
        for (int i = 0; i < sz; ++i) {
            up[k][i] = up[k-1][up[k-1][i]];
        }
    }

    int min_vaidilutes = INF;

    // Duyệt qua các khoảng ban đầu (nằm trong ngày đầu tiên)
    for (int i = 0; i < sz; ++i) {
        // Chỉ xét những khoảng bắt đầu trong phạm vi ngày gốc [0, m)
        if (a[i].l >= m) continue;

        int curr = i;
        int count = 1;
        int target = a[i].l + m;

        // Nhảy binary lifting
        for (int k = LOG - 1; k >= 0; --k) {
            int next_node = up[k][curr];
            // Nếu nhảy 2^k bước mà vẫn chưa phủ đủ M (tức R < target) thì nhảy
            if (a[next_node].r < target) {
                curr = next_node;
                count += (1 << k);
            }
        }
        
        // Sau vòng lặp, curr đang ở vị trí sát đích nhất nhưng chưa qua đích.
        // Ta cần 1 bước nhảy nữa để kiểm tra xem có qua đích không.
        int final_node = up[0][curr];
        
        if (a[final_node].r >= target) {
            min_vaidilutes = min(min_vaidilutes, count + 1);
        } else {
            // Nếu ngay cả bước cuối cũng không qua được hoặc bị kẹt
            // thì phương án bắt đầu từ i là không khả thi
        }
    }

    if (min_vaidilutes == INF) {
        cout << -1 << endl;
    } else {
        cout << min_vaidilutes << endl;
    }

    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...