Submission #1164294

#TimeUsernameProblemLanguageResultExecution timeMemory
1164294cjtsaiFire (BOI24_fire)C++20
100 / 100
165 ms78960 KiB
#include <iostream> #include <vector> #include <algorithm> #include <climits> using namespace std; struct Interval { int start, end; }; int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int N, M; cin >> N >> M; vector<Interval> intervals; // Extend intervals to the doubled timeline [0, 2M] for (int i = 0; i < N; i++){ int s, e; cin >> s >> e; if(s <= e){ intervals.push_back({s, e}); intervals.push_back({s + M, e + M}); } else { intervals.push_back({s, e + M}); } } // Sort intervals by start time sort(intervals.begin(), intervals.end(), [](const Interval &a, const Interval &b){ return a.start < b.start; }); // Build the discrete timeline B (all interval start and end times plus boundaries) vector<int> B; for (const auto &intv : intervals) { B.push_back(intv.start); B.push_back(intv.end); } B.push_back(0); B.push_back(2 * M); sort(B.begin(), B.end()); B.erase(unique(B.begin(), B.end()), B.end()); int Bsize = B.size(); // For each discrete time B[i], compute f[i]: // the farthest time reachable in one jump (using any interval with start <= B[i]) vector<int> f(Bsize, 0); int idx = 0; int current_max = 0; for (int i = 0; i < Bsize; i++){ int t = B[i]; while (idx < intervals.size() && intervals[idx].start <= t) { current_max = max(current_max, intervals[idx].end); idx++; } f[i] = current_max; } // For each B[i], define nxt[i] = index in B such that B[nxt[i]] is the maximum reachable time from B[i] vector<int> nxt(Bsize, 0); for (int i = 0; i < Bsize; i++){ int val = f[i]; int j = upper_bound(B.begin(), B.end(), val) - B.begin() - 1; nxt[i] = j; } // Build binary lifting table dp[k][i]: // dp[k][i] is the index in B reached after 2^k jumps starting from B[i]. int L = 0; while ((1 << L) <= Bsize) L++; vector<vector<int>> dp(L, vector<int>(Bsize, 0)); for (int i = 0; i < Bsize; i++){ dp[0][i] = nxt[i]; } for (int k = 1; k < L; k++){ for (int i = 0; i < Bsize; i++){ dp[k][i] = dp[k - 1][ dp[k - 1][i] ]; } } // For each candidate starting time T in [0, M), use binary lifting to compute // the minimal number of jumps needed to reach T + M. int ans = INT_MAX; for (int i = 0; i < Bsize; i++){ int T = B[i]; if(T < 0 || T >= M) continue; // Only consider starting times in [0, M) int target = T + M; int cnt = 0; int cur = i; // current index in B (represents current coverage time B[cur]) // If we're already covering [T, T+M], no jumps needed. if(B[cur] >= target){ ans = min(ans, cnt); continue; } // Use binary lifting: try the largest jump that doesn't reach the target yet. for (int k = L - 1; k >= 0; k--){ int next_idx = dp[k][cur]; if(B[next_idx] < target){ cnt += (1 << k); cur = next_idx; } } // One more jump is needed. if(B[dp[0][cur]] >= target){ cnt++; ans = min(ans, cnt); } } if(ans == INT_MAX) cout << -1 << "\n"; else cout << ans << "\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...