cplib-cpp

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub hitonanode/cplib-cpp

:heavy_check_mark: utilities/test/predecessor_problem.test.cpp

Depends on

Code

#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';
    }
}
Back to top page
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy