This documentation is automatically generated by online-judge-tools/verification-helper
View the Project on GitHub hitonanode/cplib-cpp
#include "../integer_segments.hpp" #include <iostream> #include <string> using namespace std; #define PROBLEM "https://judge.yosupo.jp/problem/predecessor_problem" int main() { cin.tie(nullptr), ios::sync_with_stdio(false); int N, Q; string T; cin >> N >> Q >> T; integer_segments<int> seg; T += '0'; int l = 0; for (int i = 0; i < int(T.size()); i++) { if (T[i] == '0') { if (l <= i - 1) seg.insert(l, i - 1); l = i + 1; } } while (Q--) { int c, k; cin >> c >> k; if (c == 0) seg.insert(k, k); if (c == 1) seg.remove(k, k); if (c == 2) cout << seg.contains(k) << '\n'; if (c == 3) cout << seg.lower_bound(k) << '\n'; if (c == 4) cout << seg.inv_lower_bound(k) << '\n'; } }
#line 2 "utilities/integer_segments.hpp" #include <iostream> #include <map> #include <utility> // CUT begin // Add/erase ranges on \mathbb{Z} // Basic implementation idea: https://satanic0258.github.io/snippets/data-structure/SegmentMap.html template <typename Int> struct integer_segments { const Int INVALID = -1; Int _sz; std::map<Int, Int> mp; integer_segments() : _sz(0) {} // Get the range [l, r] that satisfies l <= x <= r, or [INVALID, INVALID] otherwise std::pair<Int, Int> get(Int x) const { auto itr = mp.upper_bound(x); if (itr == mp.begin() or (--itr)->second < x) return std::make_pair(INVALID, INVALID); return *itr; } bool contains(Int x) const { return lower_bound(x) == x; } // Find the min. y in the set that satisfies x <= y Int lower_bound(Int x) const { auto itr = mp.upper_bound(x); if (itr != mp.begin() and std::prev(itr)->second >= x) return x; if (itr != mp.end()) return itr->first; return INVALID; } // Find the max. y in the set that satisfies y <= x Int inv_lower_bound(Int x) const { auto itr = mp.upper_bound(x); if (itr == mp.begin()) return INVALID; if ((--itr)->second >= x) return x; return itr->second; } void _mp_upd(Int l, Int r) { if (mp.count(l)) _sz -= mp[l] - l + 1; mp[l] = r, _sz += r - l + 1; } // Add {l, l + 1, ..., r} and return the merged segment which [l, r] belongs to std::pair<Int, Int> insert(Int l, Int r) { auto itl = mp.upper_bound(l), itr = mp.upper_bound(r + 1); if (itl != mp.begin() and (--itl)->second < l - 1) { ++itl; } if (itl != itr) { l = std::min(l, itl->first), r = std::max(r, std::prev(itr)->second); for (auto i = itl; i != itr; i++) _sz -= i->second - i->first + 1; mp.erase(itl, itr); } if (mp.count(l)) _sz -= mp[l] - l + 1; _mp_upd(l, r); return std::make_pair(l, r); } // Remove {l, l + 1, ..., r} void remove(Int l, Int r) { auto itl = mp.upper_bound(l), itr = mp.upper_bound(r); if (itl != mp.begin() and (--itl)->second < l) { ++itl; } if (itl == itr) { return; } Int tl = std::min(l, itl->first), tr = std::max(r, std::prev(itr)->second); for (auto i = itl; i != itr; i++) _sz -= i->second - i->first + 1; mp.erase(itl, itr); if (tl < l) _mp_upd(tl, l - 1); if (r < tr) _mp_upd(r + 1, tr); } Int count() const { return _sz; } // O((# of segments)) Int find_by_order(Int k) const { if (mp.empty()) return -1; Int hi = mp.begin()->first - 1; for (const auto &p : mp) { const Int l = p.first, r = p.second; hi = std::max(hi, l - 1); Int add = std::max(Int(0), r - hi); if (add >= k + 1) return hi + k + 1; k -= add; hi = std::max(hi, r); } return -1; } // Count elements strictly less than x, O((# of segments)) Int order_of_key(Int x) const { Int ret = 0; for (auto p : x) { if (p.first >= x) break; ret += std::min(x - 1, p.second) - p.first + 1; } return ret; } friend std::ostream &operator<<(std::ostream &os, const integer_segments &x) { os << '{'; for (auto &&p : x.mp) os << '[' << p.first << ',' << p.second << "],"; return os << '}'; } }; #line 3 "utilities/test/predecessor_problem.test.cpp" #include <string> using namespace std; #define PROBLEM "https://judge.yosupo.jp/problem/predecessor_problem" int main() { cin.tie(nullptr), ios::sync_with_stdio(false); int N, Q; string T; cin >> N >> Q >> T; integer_segments<int> seg; T += '0'; int l = 0; for (int i = 0; i < int(T.size()); i++) { if (T[i] == '0') { if (l <= i - 1) seg.insert(l, i - 1); l = i + 1; } } while (Q--) { int c, k; cin >> c >> k; if (c == 0) seg.insert(k, k); if (c == 1) seg.remove(k, k); if (c == 2) cout << seg.contains(k) << '\n'; if (c == 3) cout << seg.lower_bound(k) << '\n'; if (c == 4) cout << seg.inv_lower_bound(k) << '\n'; } }