Submission #342683

#TimeUsernameProblemLanguageResultExecution timeMemory
342683sakethDeda (COCI17_deda)C++17
140 / 140
109 ms6892 KiB
// segment_tree {{{ #include <vector> #include <cassert> template<typename T, typename AssociativeOperation> struct segment_tree { int SZ; T identity; AssociativeOperation TT; std::vector<T> data; segment_tree() {} segment_tree(int _SZ, T _identity, AssociativeOperation _TT) : SZ(_SZ), identity(_identity), TT(_TT) { data.resize(2 * SZ, identity); } // Returns the value at index i const T& operator[](int i) const { assert(0 <= i && i < SZ); return data[SZ + i]; } // Assigns fn(i) at index i for each i in [0, SZ) template<typename Function> void assign(Function fn) { for (int i = 0; i < SZ; i++) data[SZ + i] = fn(i); for (int i = SZ - 1; i; i--) data[i] = TT(data[2 * i], data[2 * i + 1]); } // Assigns v at index i void assign(int i, T v) { assert(0 <= i && i < SZ); data[i += SZ] = v; for (i /= 2; i; i /= 2) data[i] = TT(data[2 * i], data[2 * i + 1]); } // Returns the result of a left fold of the elements at indices in [first, last) over TT T accumulate(int first, int last) const { assert(0 <= first && last <= SZ); T left = identity, right = identity; for (first += SZ, last += SZ; first < last; first /= 2, last /= 2) { if (first & 1) left = TT(left, data[first++]); if (last & 1) right = TT(data[--last], right); } return TT(left, right); } }; // }}} // {{{ data_structures/segment_tree.cpp }}} #include <cassert> template<typename T, typename BinaryOperation> struct searchable_segment_tree : segment_tree<T, BinaryOperation> { using segment_tree<T, BinaryOperation>::SZ; using segment_tree<T, BinaryOperation>::identity; using segment_tree<T, BinaryOperation>::TT; using segment_tree<T, BinaryOperation>::data; searchable_segment_tree() {} // Rounds up internal size to the nearest power of 2 to enable binary search searchable_segment_tree(int _SZ, T _identity, BinaryOperation _TT) : segment_tree<T, BinaryOperation>(1 << (32 - __builtin_clz(_SZ - 1)), _identity, _TT) {} /* Returns the smallest index "last" such that p(accumulate(first, last)) * returns true. Returns SZ + 1 if no such index exists. Requires that * p(accumulate(first, last)) is non-decreasing as last increases. */ template<typename Predicate> int binary_search(int first, Predicate p) const { assert(0 <= first && first <= SZ); if (p(identity)) return first; first += SZ; T accumulator = identity; auto try_extend = [&](int bit) { assert(__builtin_ctz(first) >= bit); if (first + (1 << bit) > 2 * SZ) return false; T extended = TT(accumulator, data[first >> bit]); if (p(extended)) return false; accumulator = extended; first += 1 << bit; return true; }; int bit = 0; while (!(first & (1 << bit)) || try_extend(bit)) bit++; while (--bit >= 0) try_extend(bit); return first - SZ + 1; } }; #include <iostream> #include <climits> using namespace std; // {{{ data_structures/searchable_segment_tree }}} int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr); int N, Q; cin >> N >> Q; auto smaller = [](int a, int b) { return min(a, b); }; searchable_segment_tree<int, decltype(smaller)> sst(N, INT_MAX, smaller); for (int q = 0; q < Q; q++) { char op; int x, y; cin >> op >> x >> y; if (op == 'M') { sst.assign(y - 1, x); } else { int ans = sst.binary_search(y - 1, [&x](int v) { return v <= x; }); cout << (ans > N ? -1 : ans) << "\n"; } } return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...