Submission #711974

#TimeUsernameProblemLanguageResultExecution timeMemory
711974JohannEvent Hopping (BOI22_events)C++14
100 / 100
245 ms19568 KiB
#include "bits/stdc++.h" using namespace std; typedef long long ll; typedef vector<int> vi; typedef vector<vi> vvi; typedef pair<int, int> pii; typedef vector<pii> vpii; typedef vector<vpii> vvpii; typedef tuple<int, int, int> tiii; typedef vector<tiii> vtiii; #define sz(x) (int)(x).size() #define all(x) (x).begin(), (x).end() struct event { int s, e, idx; }; struct segtree { vpii arr; int size; void init(vector<event> &E) { size = 1; while (size < sz(E)) size *= 2; arr.assign(2 * size, {INT_MAX, -1}); for (int i = 0; i < sz(E); ++i) arr[i + size] = {E[i].s, E[i].idx}; } void setMin(int l, int r, pii v) { setMin(l, r, v, 1, 0, size); } void setMin(int l, int r, pii v, int x, int lx, int rx) { if (l <= lx && rx <= r) { arr[x] = min(arr[x], v); return; } if (r <= lx || rx <= l) return; int m = (lx + rx) / 2; setMin(l, r, v, 2 * x, lx, m); setMin(l, r, v, 2 * x + 1, m, rx); } pii queryMin(int i) { return queryMin(i, 1, 0, size); } pii queryMin(int i, int x, int lx, int rx) { if (rx - lx == 1) return arr[x]; int m = (lx + rx) / 2; pii tmp; if (i < m) tmp = queryMin(i, 2 * x, lx, m); else tmp = queryMin(i, 2 * x + 1, m, rx); return min(tmp, arr[x]); } }; int main() { ios::sync_with_stdio(false); cin.tie(0); int N, Q; cin >> N >> Q; vector<event> E(N); vpii Eb(N); for (int i = 0; i < N; ++i) { cin >> E[i].s >> E[i].e; E[i].idx = i; Eb[i] = {E[i].s, E[i].e}; } sort(all(E), [](event a, event b) { return a.s < b.s; }); vi posInSeg(N); for (int i = 0; i < N; ++i) posInSeg[E[i].idx] = i; segtree seg; seg.init(E); vvi vorg(N, vi(ceil(log2(N)) + 1)); auto cmp = [&](int a, int b) { if (Eb[a].second == Eb[b].second) return Eb[a].first > Eb[b].first; else return Eb[a].second > Eb[b].second; }; priority_queue<int, vi, decltype(cmp)> pq(cmp); for (int i = 0; i < N; ++i) pq.push(i); int pointerI = 0; while (!pq.empty()) { // move border of starts int nextBorder = Eb[pq.top()].second; while (pointerI < sz(E) && E[pointerI].s <= nextBorder) ++pointerI; // add correspondinge elements to segtree // TODO: I guess there is no need for a second queue todo int idx = pq.top(); pq.pop(); seg.setMin(0, pointerI, {Eb[idx].first, idx}); vorg[idx][0] = seg.queryMin(posInSeg[idx]).second; } for (int j = 1; j < sz(vorg[0]); ++j) for (int i = 0; i < N; ++i) vorg[i][j] = vorg[vorg[i][j - 1]][j - 1]; for (int q = 0, s, e; q < Q; ++q) { cin >> s >> e; --s, --e; if (s == e) { cout << 0 << "\n"; continue; } if (Eb[e].first <= Eb[s].second) { if (Eb[s].second <= Eb[e].second) cout << 1 << "\n"; else // then (Eb[s].second > Eb[e].second) cout << "impossible\n"; continue; } int ans = 0; int tmp = e; for (int j = sz(vorg[tmp]) - 1; j >= 0; --j) { tmp = vorg[e][j]; if (Eb[s].second < Eb[tmp].first) { e = tmp; ans += (1 << j); } } tmp = vorg[e][0]; if (Eb[tmp].first <= Eb[s].second) 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...