Submission #1124193

#TimeUsernameProblemLanguageResultExecution timeMemory
1124193macneilPassport (JOI23_passport)C++20
100 / 100
821 ms172860 KiB
#include <bits/stdc++.h> #include <ext/pb_ds/assoc_container.hpp> #include <ext/pb_ds/detail/standard_policies.hpp> #include <ext/pb_ds/tree_policy.hpp> using namespace std; using namespace __gnu_pbds; #define int long long #define pb push_back #define all(a) a.begin(), a.end() #define rall(a) a.rbegin(), a.rend() #define f(a) for(int i = 0; i<a; ++i) #define deb(a) cerr<<a<<endl; #define ordered_set tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update> typedef long long ll; typedef unsigned long long ull; typedef long double ld; typedef string str; typedef vector<str> vestr; typedef vector<int> vei; typedef vector<vector<int>> veve; struct SparseTable { vector<pair<int, int>> a; vector<vector<int>> spmin, spmax; SparseTable() {} void build(vector<pair<int, int>> c) { a = c; int n = a.size(); int log2n = log2(n) + 1; spmin.resize(log2n, vector<int>(n)); for (int i = 0; i < n; ++i) spmin[0][i] = i; for (int i = 1; i < log2n; ++i) { for (int j = 0; j < n; ++j) { int t = min(j + (1<<(i-1)), n - 1); if (a[spmin[i - 1][j]] < a[spmin[i - 1][t]]) spmin[i][j] = spmin[i - 1][j]; else spmin[i][j] = spmin[i - 1][t]; } } spmax.resize(log2n, vector<int>(n)); for (int i = 0; i < n; ++i) spmax[0][i] = i; for (int i = 1; i < log2n; ++i) { for (int j = 0; j < n; ++j) { int t = min(j + (1<<(i-1)), n - 1); if (a[spmax[i - 1][j]] > a[spmax[i - 1][t]]) spmax[i][j] = spmax[i - 1][j]; else spmax[i][j] = spmax[i - 1][t]; } } } int min_ind(int l, int r) { int lg2 = log2(r - l + 1); r++; if (a[spmin[lg2][l]] < a[spmin[lg2][r - (1<<lg2)]]) return spmin[lg2][l]; return spmin[lg2][r - (1<<lg2)]; } pair<int, int> get_min(int l, int r) { int lg2 = log2(r - l + 1); r++; if (a[spmin[lg2][l]] < a[spmin[lg2][r - (1<<lg2)]]) return a[spmin[lg2][l]]; return a[spmin[lg2][r - (1<<lg2)]]; } int max_ind(int l, int r) { int lg2 = log2(r - l + 1); r++; if (a[spmax[lg2][l]] > a[spmax[lg2][r - (1<<lg2)]]) return spmax[lg2][l]; return spmax[lg2][r - (1<<lg2)]; } pair<int, int> get_max(int l, int r) { int lg2 = log2(r - l + 1); r++; if (a[spmax[lg2][l]] > a[spmax[lg2][r - (1<<lg2)]]) return a[spmax[lg2][l]]; return a[spmax[lg2][r - (1<<lg2)]]; } }; const int INF = 1e8; struct Node { pair<int, int> mx; }; struct SegmentTree { vector<Node> tr; int sz; SegmentTree(vector<int> a) { int n = a.size(); sz = (1ll<<(int)(log2(n)))*2; tr.resize(2*sz); for (int i = 0; i < 2 * sz; ++i) tr[i] = {{-INF, -INF}}; for (int i = 0; i < n; ++i) { tr[i + sz - 1] = {{a[i], i}}; } for (int i = sz - 2; i >= 0; --i) tr[i] = merge(tr[2 * i + 1], tr[2 * i + 2]); } Node merge(Node a, Node b) { return {max(a.mx, b.mx)}; } Node get(int v, int l, int r, int ql, int qr) { if(ql <= l && qr >= r) { return tr[v]; } if(l >= qr || r <= ql) return {{-INF, -INF}}; int m = (l + r) / 2; return merge(get(2 * v + 1, l, m, ql, qr), get(2 * v + 2, m, r, ql, qr)); }; Node get(int ql, int qr) { return get(0, 0, sz, ql, qr); } void update(int v, int l, int r, int ind, pair<int, int> x) { if(l > ind || r <= ind) return; if(r == l + 1) { tr[v].mx = x; return; } int m = (l + r) / 2; update(2*v+1, l, m, ind, x); update(2*v+2, m, r, ind, x); tr[v].mx = max(tr[2*v+1].mx, tr[2*v+2].mx); } void update(int ind) { pair<int, int> x = {-INF, -INF}; update(0, 0, sz, ind, x); } }; struct SegmentTree2 { vector<Node> tr; int sz; SegmentTree2(vector<int> a) { int n = a.size(); sz = (1ll<<(int)(log2(n)))*2; tr.resize(2*sz); for (int i = 0; i < 2 * sz; ++i) tr[i] = {{INF, INF}}; for (int i = 0; i < n; ++i) { tr[i + sz - 1] = {{a[i], i}}; } for (int i = sz - 2; i >= 0; --i) tr[i] = merge(tr[2 * i + 1], tr[2 * i + 2]); } Node merge(Node a, Node b) { return {min(a.mx, b.mx)}; } Node get(int v, int l, int r, int ql, int qr) { if(ql <= l && qr >= r) { return tr[v]; } if(l >= qr || r <= ql) return {{INF, INF}}; int m = (l + r) / 2; return merge(get(2 * v + 1, l, m, ql, qr), get(2 * v + 2, m, r, ql, qr)); }; Node get(int ql, int qr) { return get(0, 0, sz, ql, qr); } void update(int v, int l, int r, int ind, pair<int, int> x) { if(l > ind || r <= ind) return; if(r == l + 1) { tr[v].mx = x; return; } int m = (l + r) / 2; update(2*v+1, l, m, ind, x); update(2*v+2, m, r, ind, x); tr[v].mx = min(tr[2*v+1].mx, tr[2*v+2].mx); } void update(int ind) { pair<int, int> x = {INF, INF}; update(0, 0, sz, ind, x); } }; void solve() { int n; cin >> n; vector<int> l(n), r(n); f(n) { cin >> l[i] >> r[i]; l[i]--; r[i]--; } // if (n > 2500) { // int q, k; // cin >> q >> k; // int ans = 1, R = r[0], R2 = 0; // while (R != n - 1) { // int tt = 0; // for (int i = R2 + 1; i <= R; ++i) { // tt = max(tt, r[i]); // } // if (tt <= R) { // ans = -1; // break; // } // ans++; // R2 = R; // R = tt; // } // cout << ans << '\n'; // return; // } set<pair<pair<int, int>, int>> ord; // {{dp[i], r[i]}, i} // for (auto e : ord) cout << e << ' '; cout << '\n'; vector<bool> used(n); vector<pair<int, int>> dp1(n, {1e8, 1e8}); SegmentTree cur(r); SegmentTree2 cur2(l); f(n) if (l[i] == 0) ord.insert({{1, -r[i]}, i}); f(n) if (l[i] == 0) used[i] = 1; f(n) if (l[i] == 0) dp1[i].first = 1; f(n) if (l[i] == 0) dp1[i].second = -r[i]; f(n) if (l[i] == 0) cur.update(i); f(n) if (l[i] == 0) cur2.update(i); while(ord.size()) { int i = (*ord.begin()).second; // cout << i << ' '; dp1[i].second = min(dp1[i].second, -r[i]); while(1) { pair<int, int> au = cur.get(0, i).mx; // cout << au.second << endl; if (au.first < i) break; swap(au.first, au.second); dp1[au.first] = {dp1[i].first + 1, dp1[i].second}; dp1[au.first].second = min(dp1[au.first].second, -r[au.first]); ord.insert({dp1[au.first], au.first}); cur.update(au.first); cur2.update(au.first); } while(1) { pair<int, int> au = cur2.get(i, n).mx; if (au.first > i) break; swap(au.first, au.second); dp1[au.first] = {dp1[i].first + 1, dp1[i].second}; dp1[au.first].second = min(dp1[au.first].second, -r[au.first]); ord.insert({dp1[au.first], au.first}); cur.update(au.first); cur2.update(au.first); } // cout << endl; ord.erase(ord.begin()); } // for (auto e : dp1) cout << e.first << ' '; cout << '\n'; // for (auto e : ord) cout << e << ' '; cout << '\n'; vector<pair<int, int>> dp2(n, {1e8, 1e8}); SegmentTree cur3(r); SegmentTree2 cur4(l); used.clear(); used.resize(n); f(n) if (r[i] == n - 1) ord.insert({{1, l[i]}, i}); f(n) if (r[i] == n - 1) used[i] = 1; f(n) if (r[i] == n - 1) dp2[i].first = 1; f(n) if (r[i] == n - 1) dp2[i].second = l[i]; f(n) if (r[i] == n - 1) cur3.update(i); f(n) if (r[i] == n - 1) cur4.update(i); while(ord.size()) { int i = (*ord.begin()).second; dp2[i].second = min(dp2[i].second, l[i]); while(1) { pair<int, int> au = cur3.get(0, i).mx; if (au.first < i) break; swap(au.first, au.second); dp2[au.first] = {dp2[i].first + 1, dp2[i].second}; dp2[au.first].second = min(dp2[au.first].second, l[au.first]); ord.insert({dp2[au.first], au.first}); cur3.update(au.first); cur4.update(au.first); } while(1) { pair<int, int> au = cur4.get(i, n).mx; // cout << "WOW" << au.first << endl; if (au.first > i) break; swap(au.first, au.second); dp2[au.first] = {dp2[i].first + 1, dp2[i].second}; dp2[au.first].second = min(dp2[au.first].second, l[au.first]); ord.insert({dp2[au.first], au.first}); cur3.update(au.first); cur4.update(au.first); } ord.erase(ord.begin()); } // for (auto e : dp1) cout << e.first << ' '; cout << '\n'; int q; cin >> q; SparseTable fdp1, fdp2; fdp1.build(dp1); fdp2.build(dp2); for (int i = 0; i < q; ++i) { int x; cin >> x; --x; if (dp1[x].first > 2 * n || dp2[x].first > 2 * n) { cout << "-1\n"; continue; } int ans = dp1[x].first; if (dp1[x].second != -(n - 1)) ans += fdp2.get_min(0, -dp1[x].second).first; int ans2 = dp2[x].first; if (dp2[x].second != 0) ans2 += fdp1.get_min(dp2[x].second, n - 1).first; cout << min(ans, ans2) << '\n'; } } signed main() { ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); // freopen("a.in", "r", stdin); // freopen("a.out", "w", stdout); int tc = 1; // cin >> tc; for (int t = 1; t <= tc; t++) { // cout << "Case #" << t << ": "; solve(); } }
#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...