Submission #395969

#TimeUsernameProblemLanguageResultExecution timeMemory
395969rama_pangHedgehog Daniyar and Algorithms (IZhO19_sortbooks)C++17
100 / 100
1271 ms109368 KiB
#include <bits/stdc++.h> using namespace std; class SegTree { public: int sz; vector<int> tree; SegTree(int sz) : sz(sz), tree(2 * sz, 0) {} void Modify(int p, int x) { for (p += sz; p > 0; p /= 2) tree[p] = max(tree[p], x); } int Query(int l, int r) { int res = 0; for (l += sz, r += sz + 1; l < r; l /= 2, r /= 2) { if (l & 1) res = max(res, tree[l++]); if (r & 1) res = max(res, tree[--r]); } return res; } }; int main() { ios::sync_with_stdio(0); cin.tie(0); int N, Q; cin >> N >> Q; vector<int> A(N); for (int i = 0; i < N; i++) { cin >> A[i]; } vector<int> ans(Q); vector<vector<array<int, 3>>> query(N); for (int i = 0; i < Q; i++) { int l, r, k; cin >> l >> r >> k; l--, r--; query[l].push_back({r, k, i}); } // Solution: // // For a range [L, R], we want to pick // i, j, s.t. L <= i < k <= R, A[i] > A[j], // where A[i] + A[j] is maximal. Then, if // A[i] + A[j] > k, the books cannot be sorted; // otherwise, it can. // // Note that for i < j, A[i] > A[j], since we can // only swap adjacent books, at some point in sorting // A[i] and A[j] must be adjacent, and we must swap them. // // Let's sweep from right to left. Note that for i < j, // A[i] > A[j]: // - If there exist i < k < j, s.t. A[j] < A[i] < A[k], the pair // (k, j) is strictly better. // - If there exist i < k < j, s.t. A[i] > A[k] > A[j], the pair // (i, k) is strictly better. // // Note that this means, for all (i, j), it is optimal if all indices // i < k < j, either A[k] < min(A[i], A[j]) must hold. // // This means, we only need to care about the nearest element to the left // of j which is greater than A[j]. This is only O(N), and can be computed // easily. // // We can answer everything offline in O((N + Q) log N). vector<vector<int>> candidates(N); { // Compute candidates, (i, j) is good if i is nearest element greater than A[j] to the right vector<int> st; for (int i = 0; i < N; i++) { while (!st.empty() && A[st.back()] <= A[i]) { st.pop_back(); } if (!st.empty()) { candidates[st.back()].emplace_back(i); } st.emplace_back(i); } } SegTree seg(N); for (int l = N - 1; l >= 0; l--) { for (auto r : candidates[l]) { seg.Modify(r, A[l] + A[r]); } for (auto [r, k, q] : query[l]) { ans[q] = seg.Query(l, r) <= k; } } for (int i = 0; i < Q; i++) { cout << ans[i] << '\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...