Submission #1351942

#TimeUsernameProblemLanguageResultExecution timeMemory
1351942MDSProEvent Hopping (BOI22_events)C++17
20 / 100
89 ms16304 KiB
#include <bits/stdc++.h>
using namespace std;

const int LOG = 17;

int main(){
    cin.tie(0)->sync_with_stdio(0);
    
    int n, q;
    cin >> n >> q;
    
    vector<int> s(n), e(n);
    vector<int> all;
    
    for(int i = 0; i < n; ++i){
        cin >> s[i] >> e[i];
        all.push_back(s[i]);
        all.push_back(e[i]);
    }
    
    sort(all.begin(), all.end());
    all.erase(unique(all.begin(), all.end()), all.end());
    int m = all.size();
    
    auto compress = [&](int x){
        return int(lower_bound(all.begin(), all.end(), x) - all.begin());
    };
    
    vector<int> order(n);
    iota(order.begin(), order.end(), 0);
    sort(order.begin(), order.end(), [&](int a, int b){
        return e[a] < e[b];
    });
    
    vector<pair<int,int>> tree(4 * m, {INT_MAX, -1});
    
    auto update = [&](auto& self, int v, int tl, int tr, int pos, int val, int idx) -> void {
        if(tl == tr){
            if(val < tree[v].first) tree[v] = {val, idx};
            return;
        }
        int tm = (tl + tr) / 2;
        if(pos <= tm) self(self, v*2, tl, tm, pos, val, idx);
        else self(self, v*2+1, tm+1, tr, pos, val, idx);
        tree[v] = min(tree[v*2], tree[v*2+1]);
    };
    
    auto query = [&](auto& self, int v, int tl, int tr, int l, int r) -> pair<int,int> {
        if(l > r) return {INT_MAX, -1};
        if(l == tl && r == tr) return tree[v];
        int tm = (tl + tr) / 2;
        return min(
            self(self, v*2, tl, tm, l, min(r, tm)),
            self(self, v*2+1, tm+1, tr, max(l, tm+1), r)
        );
    };
    
    vector<array<int, LOG>> prev(n);
    for(int i = 0; i < n; ++i){
        fill(prev[i].begin(), prev[i].end(), -1);
    }
    
    for(int i = 0; i < n; ++i){
        int idx = order[i];
        int si = compress(s[idx]);
        int ei = compress(e[idx]);
        
        auto [_, best] = query(query, 1, 0, m-1, si, ei);
        prev[idx][0] = best;
        
        update(update, 1, 0, m-1, ei, s[idx], idx);
    }
    
    for(int k = 1; k < LOG; ++k){
        for(int i = 0; i < n; ++i){
            if(prev[i][k-1] != -1){
                prev[i][k] = prev[prev[i][k-1]][k-1];
            }
        }
    }
    
    auto canSwitch = [&](int a, int b) -> bool {
        return s[b] <= e[a] && e[a] <= e[b];
    };
    
    while(q--){
        int st, en;
        cin >> st >> en;
        --st; --en;
        
        if(st == en){
            cout << "0\n";
            continue;
        }
        
        if(canSwitch(st, en)){
            cout << "1\n";
            continue;
        }
        
        if(e[st] >= e[en]){
            cout << "impossible\n";
            continue;
        }
        
        int cur = en;
        int ans = 0;
        
        for(int k = LOG - 1; k >= 0; --k){
            int nxt = prev[cur][k];
            // Don't jump if:
            // 1. nxt doesn't exist
            // 2. st can switch to nxt (we found our target)
            // 3. nxt ends before or at st (we'd be jumping past st)
            if(nxt != -1 && !canSwitch(st, nxt) && e[nxt] > e[st]){
                cur = nxt;
                ans += (1 << k);
            }
        }
        
        if(canSwitch(st, cur)){
            cout << ans + 1 << "\n";
        } else if(prev[cur][0] != -1 && canSwitch(st, prev[cur][0])){
            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...