Submission #882939

#TimeUsernameProblemLanguageResultExecution timeMemory
882939WLZIndex (COCI21_index)C++17
110 / 110
886 ms64848 KiB
#include <vector> #include <functional> #include <numeric> template<typename T> constexpr T my_add(T a, T b) { return a + b; } template<typename T, auto f = my_add<T> > class persistent_segment_tree { static_assert(std::is_convertible_v<decltype(f), std::function<T(T, T)> >); private: unsigned int n, root; std::vector<T> st; std::vector<unsigned int> lc, rc; unsigned int build(unsigned int cl, unsigned int cr, const std::vector<T> &a) { if (cl + 1 == cr) { st.push_back(a[cl]); lc.push_back(0); rc.push_back(0); return st.size() - 1; } unsigned int cm = (cl + cr) >> 1; unsigned int tmp_l = build(cl, cm, a), tmp_r = build(cm, cr, a); lc.push_back(tmp_l); rc.push_back(tmp_r); st.push_back(f(st[tmp_l], st[tmp_r])); return st.size() - 1; } T query(unsigned int idx, unsigned int cl, unsigned int cr, unsigned int l, unsigned int r) const { if (l <= cl && cr <= r) return st[idx]; unsigned int cm = (cl + cr) >> 1; if (r <= cm) return query(lc[idx], cl, cm, l, r); if (l >= cm) return query(rc[idx], cm, cr, l, r); return f(query(lc[idx], cl, cm, l, r), query(rc[idx], cm, cr, l, r)); } unsigned int update(unsigned int idx, unsigned int cl, unsigned int cr, unsigned int pos, const T &val) { if (cl + 1 == cr) { st.push_back(val); lc.push_back(0); rc.push_back(0); return st.size() - 1; } unsigned int cm = (cl + cr) >> 1; unsigned int tmp_l = lc[idx], tmp_r = rc[idx]; if (pos < cm) tmp_l = update(lc[idx], cl, cm, pos, val); else tmp_r = update(rc[idx], cm, cr, pos, val); lc.push_back(tmp_l); rc.push_back(tmp_r); st.push_back(f(st[tmp_l], st[tmp_r])); return st.size() - 1; } public: // Note: hasn't been tested yet persistent_segment_tree() : n(0) {} explicit persistent_segment_tree(const std::vector<T> &a) : n(a.size()) { root = build(0, n, a); } // Note: hasn't been tested yet explicit persistent_segment_tree(size_t _n) : persistent_segment_tree(std::vector<T>(_n)) {} persistent_segment_tree(size_t _n, const T &x) : persistent_segment_tree(std::vector<T>(_n, x)) {} unsigned int original_root() const { return root; } T query(unsigned int idx, unsigned int l, unsigned int r) const { return query(idx, 0, n, l, r); } // Note: hasn't been tested yet T query(unsigned int idx, unsigned int l) const { return query(idx, l, l + 1); } unsigned int update(unsigned int idx, unsigned int pos, const T &val) { return update(idx, 0, n, pos, val); } // Note: hasn't been tested yet size_t size() const { return n; } }; #include <iostream> #include <map> #include <algorithm> const int INF = 0x3f3f3f3f; int main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int n, q; std::cin >> n >> q; std::vector<int> p(n + 1); std::vector< std::vector<int> > mp((int) 2e5 + 5); for (int i = 1; i <= n; i++) std::cin >> p[i], mp[p[i]].push_back(i); persistent_segment_tree<int> st(n + 1, 0); std::vector<int> roots((int) 2e5 + 5); roots[(int) 2e5 + 1] = st.original_root(); for (int i = (int) 2e5; i >= 0; i--) { roots[i] = roots[i + 1]; for (auto &idx : mp[i]) roots[i] = st.update(roots[i], idx, 1); } while (q--) { int l, r; std::cin >> l >> r; int lo = 1, hi = n; while (lo < hi) { int mid = (lo + hi + 1) / 2; if (st.query(roots[mid], l, r + 1) >= mid) { lo = mid; } else { hi = mid - 1; } } std::cout << lo << '\n'; } return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...