Submission #1176121

#TimeUsernameProblemLanguageResultExecution timeMemory
1176121quanndEvent Hopping (BOI22_events)C++20
10 / 100
1594 ms19644 KiB
#include <bits/stdc++.h>
using namespace std;
 
struct Node {
    int l, r;
};
 
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int N, Q;
    cin >> N >> Q;
    vector<Node> nodes(N);
    vector<int> compVals;
    for (int i = 0; i < N; i++){
        cin >> nodes[i].l >> nodes[i].r;
        compVals.push_back(nodes[i].l);
        compVals.push_back(nodes[i].r);
    }
    // Coordinate compression
    sort(compVals.begin(), compVals.end());
    compVals.erase(unique(compVals.begin(), compVals.end()), compVals.end());
    auto comp = [&](int x) -> int {
        return int(lower_bound(compVals.begin(), compVals.end(), x) - compVals.begin());
    };
    
    // Sắp xếp các nút theo l để dễ truy vấn "cho x, tìm max r"
    vector<int> order(N);
    iota(order.begin(), order.end(), 0);
    sort(order.begin(), order.end(), [&](int a, int b){
        return nodes[a].l < nodes[b].l;
    });
    
    // LOG: số lớp binary lifting (số bước nhảy tối đa giả sử)
    const int LOG = 20;
    
    // Với mỗi truy vấn, ta sẽ xây dựng hàm f chỉ với các nút có r <= r_b của truy vấn đó.
    // Hàm f: với một giá trị hiện tại (đã nén) x, trả về giá trị max { comp(nodes[i].r) }
    // với các nút i thỏa nodes[i].l <= compVals[x] và nodes[i].r <= r_b.
    for (int qi = 0; qi < Q; qi++){
        int a, b;
        cin >> a >> b;
        a--; b--; // chuyển về 0-indexed
        
        if(a == b){
            cout << 0 << "\n";
            continue;
        }
        
        int Ra = nodes[a].r, Rb = nodes[b].r, Lb = nodes[b].l;
        // Nếu không thoả điều kiện cần thiết để có đường đi (do r chỉ tăng)
        if(Ra > Rb){
            cout << "impossible\n";
            continue;
        }
        // Nếu có thể chuyển trực tiếp từ a đến b (vì r_a >= l_b)
        if(Ra >= Lb){
            cout << 1 << "\n";
            continue;
        }
        
        // Xây dựng mảng F cho hàm f, trên không gian các giá trị đã nén.
        // F[i] = giá trị lớn nhất (đã nén) của nodes[j].r với các nút có
        // nodes[j].l <= compVals[i] và nodes[j].r <= Rb.
        int m = compVals.size();
        vector<int> F(m, -1);
        // Duyệt theo thứ tự tăng của l (đã được sắp xếp trong order)
        for (int idx : order) {
            if(nodes[idx].r <= Rb){
                int pos = comp(nodes[idx].l);
                int rpos = comp(nodes[idx].r);
                F[pos] = max(F[pos], rpos);
            }
        }
        // Xây dựng tiền xử lý "prefix max" trên F:
        for (int i = 1; i < m; i++){
            F[i] = max(F[i], F[i - 1]);
        }
        // Hàm f: cho trạng thái hiện tại x (đã nén), trả về F[x].
        auto f_func = [&](int x) -> int {
            return F[x];
        };
        
        int start = comp(Ra);
        int goal = comp(Lb);
        // Nếu giá trị ban đầu đã vượt qua goal (nghĩa là có thể chuyển trực tiếp)
        if(start >= goal){
            cout << 1 << "\n";
            continue;
        }
        
        // Xây dựng bảng binary lifting cho hàm f.
        vector<vector<int>> dp(LOG, vector<int>(m, 0));
        for (int i = 0; i < m; i++){
            dp[0][i] = f_func(i);
        }
        for (int k = 1; k < LOG; k++){
            for (int i = 0; i < m; i++){
                dp[k][i] = dp[k - 1][ dp[k - 1][i] ];
            }
        }
        
        // Sử dụng binary lifting để nhảy từ start đến vị trí có giá trị >= goal
        int cur = start;
        int ans = 0;
        for (int k = LOG - 1; k >= 0; k--){
            if(dp[k][cur] < goal){
                cur = dp[k][cur];
                ans += (1 << k);
            }
        }
        // Bước nhảy cuối cùng
        if(f_func(cur) >= goal){
            cout << ans + 2 << "\n";
        } else {
            cout << "impossible\n";
        }
    }
    
    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...