Submission #1176004

#TimeUsernameProblemLanguageResultExecution timeMemory
1176004minhpkEvent Hopping (BOI22_events)C++20
0 / 100
162 ms52172 KiB
#include <bits/stdc++.h> #define int long long using namespace std; int a, q; pair<int,int> z[1000005]; vector<int> v; struct node { int l, id; }; const int INF = 1e16; node f[4000005]; // Hàm combine: chọn nút có giá trị l nhỏ hơn; nếu bằng nhau thì chọn nút có id lớn hơn. node combine(const node &left, const node &right) { if (left.l < right.l) return left; if (left.l == right.l && left.id > right.id) return left; return right; } void build(int id, int l, int r) { if (l == r) { f[id] = {INF, INF}; return; } int mid = (l + r) / 2; build(id * 2, l, mid); build(id * 2 + 1, mid + 1, r); f[id] = combine(f[id * 2], f[id * 2 + 1]); } void update(int id, int l, int r, int pos, int L, int idx) { if (l == r) { // Cập nhật nút tại vị trí pos với thông tin {L, idx} f[id] = combine(f[id], {L, idx}); return; } int mid = (l + r) / 2; if (pos <= mid) update(id * 2, l, mid, pos, L, idx); else update(id * 2 + 1, mid + 1, r, pos, L, idx); f[id] = combine(f[id * 2], f[id * 2 + 1]); } node query(int id, int l, int r, int ql, int qr) { if (qr < l || ql > r) return {INF, INF}; if (ql <= l && r <= qr) return f[id]; int mid = (l + r) / 2; node leftNode = query(id * 2, l, mid, ql, qr); node rightNode = query(id * 2 + 1, mid + 1, r, ql, qr); return combine(leftNode, rightNode); } int up[100005][25]; int cost[100005][25]; signed main() { ios_base::sync_with_stdio(false); cin.tie(NULL); cin >> a >> q; for (int i = 1; i <= a; i++) { cin >> z[i].first >> z[i].second; v.push_back(z[i].first); v.push_back(z[i].second); } // Tiến hành coordinate compression sort(v.begin(), v.end()); v.erase(unique(v.begin(), v.end()), v.end()); int n = v.size(); for (int i = 1; i <= a; i++) { z[i].first = lower_bound(v.begin(), v.end(), z[i].first) - v.begin() + 1; z[i].second = lower_bound(v.begin(), v.end(), z[i].second) - v.begin() + 1; } // Xây dựng cây phân đoạn trên khoảng [1, n] build(1, 1, n); // Với mỗi khoảng, cập nhật tại vị trí = z[i].second giá trị là {z[i].first, i} for (int i = 1; i <= a; i++) { update(1, 1, n, z[i].second, z[i].first, i); } // Xây dựng bảng nhảy một bước (up[i][0]) và chi phí tương ứng. // Với mỗi khoảng i, truy vấn trên [z[i].first, z[i].second] để tìm khoảng "tối ưu" nối được với i. for (int i = 1; i <= a; i++) { node res = query(1, 1, n, z[i].first, z[i].second); // Nếu không tìm được khoảng nào khác (res.id == i) thì không có bước nhảy if (res.id == i) { up[i][0] = i; cost[i][0] = 0; } else { up[i][0] = res.id; cost[i][0] = 1; } } // Xây dựng bảng nhảy đôi (binary lifting) for (int j = 1; j <= 20; j++) { for (int i = 1; i <= a; i++) { up[i][j] = up[up[i][j - 1]][j - 1]; cost[i][j] = cost[i][j - 1] + cost[up[i][j - 1]][j - 1]; } } // Xử lý truy vấn: // Mục tiêu: từ khoảng x có thể nối chuỗi tới khoảng y với số bước tối thiểu while (q--) { int x, y; cin >> x >> y; if (x == y) { cout << 0 << "\n"; continue; } // Nếu khoảng bắt đầu của x không nhỏ hơn kết thúc của y, không nối được if (z[x].first >= z[y].second) { cout << "impossible" << "\n"; continue; } int p = y; int ans = 0; // Sử dụng nhảy nhị phân từ y về x (tìm khoảng mà z[x].second có thể nối được) for (int i = 20; i >= 0; i--) { int candidate = up[p][i]; // Nếu khoảng candidate vẫn có đầu trái lớn hơn z[x].second, ta có thể nhảy ngược tiếp if (z[candidate].first > z[x].second) { ans += cost[p][i]; p = candidate; } } // Kiểm tra sau nhảy nhị phân, nếu z[x].second nối được với khoảng p thì cộng thêm 1 bước if (z[x].second >= z[p].first) { cout << ans + 1 << "\n"; } else { // Thử nhảy thêm một bước nữa p = up[p][0]; if (z[x].second >= z[p].first) { 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...