Felix's Library

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

View the Project on GitHub fffelix-huang/CP-stuff

:heavy_check_mark: test/data-structure/ordered-set/yosupo-Predecessor-Problem.test.cpp

Depends on

Code

#define PROBLEM "https://judge.yosupo.jp/problem/predecessor_problem"

#include <iostream>

#include "../../../library/data-structure/ordered-set.hpp"

using namespace std;
using namespace felix;

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	int n, q;
	cin >> n >> q;
	ordered_set<int> tree;
	string s;
	cin >> s;
	for(int i = 0; i < n; i++) {
		if(s[i] == '1') {
			tree.insert(i);
		}
	}
	while(q--) {
		int type, x;
		cin >> type >> x;
		if(type == 0) {
			tree.insert(x);
		} else if(type == 1) {
			tree.erase(x);
		} else if(type == 2) {
			cout << tree.count(x) << "\n";
		} else if(type == 3) {
			int index = tree.lower_bound(x);
			int ans = -1;
			if(index < tree.size()) {
				ans = tree.get(index);
			}
			cout << ans << "\n";
		} else {
			int index = tree.upper_bound(x) - 1;
			int ans = -1;
			if(index >= 0) {
				ans = tree.get(index);
			}
			cout << ans << "\n";
		}
	}
	return 0;
}
#line 1 "test/data-structure/ordered-set/yosupo-Predecessor-Problem.test.cpp"
#define PROBLEM "https://judge.yosupo.jp/problem/predecessor_problem"

#include <iostream>

#line 2 "library/data-structure/ordered-set.hpp"
#include <tuple>

#include <cassert>

#include <iterator>

#include <functional>

#line 2 "library/random/rng.hpp"
#include <chrono>

namespace felix {

inline unsigned long long rng() {
	static unsigned long long SEED = std::chrono::steady_clock::now().time_since_epoch().count();
	SEED ^= SEED << 7;
	SEED ^= SEED >> 9;
	return SEED;
}

} // namespace felix
#line 5 "library/bst/rbst-base.hpp"

namespace felix {

namespace internal {

template<class node_t, class Comp = std::less<decltype(node_t::key)>>
struct rbst_base {
	using key_type = decltype(node_t::key);

private:
	static const Comp Compare;

public:
	static node_t* merge(node_t* a, node_t* b) {
		if(a == nullptr || b == nullptr) {
			return a != nullptr ? a : b;
		}
		if((int) (((unsigned int) rng() * 1LL * (a->size + b->size)) >> 32) < a->size) {
			a->push();
			a->r = merge(a->r, b);
			a->pull();
			return a;
		} else {
			b->push();
			b->l = merge(a, b->l);
			b->pull();
			return b;
		}
	}

	static std::pair<node_t*, node_t*> split(node_t* v, int k) {
		if(v == nullptr) {
			return {nullptr, nullptr};
		}
		v->push();
		if(k <= get_size(v->l)) {
			auto p = split(v->l, k);
			v->l = p.second;
			if(p.first != nullptr) {
				p.first->p = nullptr;
			}
			v->pull();
			return {p.first, v};
		} else {
			auto p = split(v->r, k - get_size(v->l) - 1);
			v->r = p.first;
			if(p.second != nullptr) {
				p.second->p = nullptr;
			}
			v->pull();
			return {v, p.second};
		}
	}

	static std::tuple<node_t*, node_t*, node_t*> split_range(node_t* v, int l, int r) {
		auto p = split(v, l);
		auto q = split(p.second, r - l);
		return {p.first, q.first, q.second};
	}

	static void insert(node_t*& v, int k, const key_type& val) {
		auto p = split(v, k);
		v = merge(p.first, merge(new node_t(val), p.second));
	}

	static void erase(node_t*& v, int k) {
		auto p = split_range(v, k, k + 1);
		delete std::get<1>(p);
		v = merge(std::get<0>(p), std::get<2>(p));
	}

	static int lower_bound(node_t* v, const key_type& val) {
		if(v == nullptr) {
			return 0;
		}
		// TTTTFFFF

		//     ^

		if(Compare(v->key, val)) {
			return get_size(v->l) + 1 + lower_bound(v->r, val);
		} else {
			return lower_bound(v->l, val);
		}
	}

	static int upper_bound(node_t* v, const key_type& val) {
		// 1 2 3 3 4

		//         ^

		// F F F F T

		if(v == nullptr) {
			return 0;
		}
		if(!Compare(val, v->key)) {
			return get_size(v->l) + 1 + upper_bound(v->r, val);
		} else {
			return upper_bound(v->l, val);
		}
	}

	static key_type get(node_t*& v, int k) {
		auto p = split_range(v, k, k + 1);
		key_type res = std::get<1>(p)->key;
		v = merge(std::get<0>(p), merge(std::get<1>(p), std::get<2>(p)));
		return res;
	}

	static int get_index(node_t* v) {
		int k = get_size(v->l);
		while(v->p != nullptr) {
			if(v == v->p->r) {
				k++;
				if(v->p->l != nullptr) {
					k += v->p->l->size;
				}
			}
			v = v->p;
		}
		return k;
	}

	static void clear(node_t*& v) {
		postorder(v, [](node_t* v) {
			delete v;
		});
		v = nullptr;
	}

	static node_t* next(node_t* v) {
		if(v->r == nullptr) {
			while(v->p != nullptr && v->p->r == v) {
				v = v->p;
			}
			return v->p;
		}
		v->push();
		if(v->r == nullptr) {
			return nullptr;
		}
		v = v->r;
		while(v->l != nullptr) {
			v->push();
			v = v->l;
		}
		return v;
	}

	static node_t* prev(node_t* v) {
		if(v->l == nullptr) {
			while(v->p != nullptr && v->p->l == v) {
				v = v->p;
			}
			return v->p;
		}
		v->push();
		if(v->l == nullptr) {
			return nullptr;
		}
		v = v->l;
		while(v->r != nullptr) {
			v->push();
			v = v->r;
		}
		return v;
	}

	template<class Func>
	static void preorder(node_t* v, const Func& f) {
		auto rec = [&](auto rec, node_t* v) -> void {
			if(v == nullptr) {
				return;
			}
			v->push();
			f(v);
			rec(rec, v->l);
			rec(rec, v->r);
		};
		rec(rec, v);
	}

	template<class Func>
	static void inorder(node_t* v, const Func& f) {
		auto rec = [&](auto rec, node_t* v) -> void {
			if(v == nullptr) {
				return;
			}
			v->push();
			rec(rec, v->l);
			f(v);
			rec(rec, v->r);
		};
		rec(rec, v);
	}

	template<class Func>
	static void postorder(node_t* v, const Func& f) {
		auto rec = [&](auto rec, node_t* v) -> void {
			if(v == nullptr) {
				return;
			}
			v->push();
			rec(rec, v->l);
			rec(rec, v->r);
			f(v);
		};
		rec(rec, v);
	}

	static int size(node_t* v) { return get_size(v); }
	static bool empty(node_t* v) { return v == nullptr; }

private:
	static int get_size(node_t* v) { return v != nullptr ? v->size : 0; }
};

template<class node_t, class Comp> const Comp rbst_base<node_t, Comp>::Compare = Comp();

} // namespace internal


} // namespace felix

#line 7 "library/data-structure/ordered-set.hpp"

namespace felix {

namespace internal {

template<class T>
struct node_t {
	T key;
	int size = 1;
	node_t* l = nullptr;
	node_t* r = nullptr;
	node_t* p = nullptr;

	node_t() {}
	node_t(const T& x) : key(x) {}

	void push() {}

	void pull() {
		size = 1;
		if(l != nullptr) {
			size += l->size;
			l->p = this;
		}
		if(r != nullptr) {
			size += r->size;
			r->p = this;
		}
	}
};

} // namespace internal


template<class T, class Comp = std::less<T>>
struct ordered_set {
	using node_t = typename internal::node_t<T>;
	using base = internal::rbst_base<node_t, Comp>;

private:
	node_t* root = nullptr;
	ordered_set(node_t* v) : root(v) {}

public:
	ordered_set() {}
	ordered_set(const ordered_set& other) {
		clear();
		base::preorder(other.root, [&](node_t* v) {
			root = base::merge(root, new node_t(v->key));
		});
	}

	~ordered_set() { clear(); }

	int size() const { return base::size(root); }
	bool empty() const { return base::empty(root); }
	void clear() { base::clear(root); }

	int lower_bound(const T& val) const { return base::lower_bound(root, val); }
	int upper_bound(const T& val) const { return base::upper_bound(root, val); }

	T get(int k) {
		assert(0 <= k && k < size());
		return base::get(root, k);
	}

	int count(const T& val) {
		int k = lower_bound(val);
		return k < size() && get(k) == val;
	}

	int insert(const T& val) {
		int k = lower_bound(val);
		if(k == size() || get(k) != val) {
			base::insert(root, k, val);
		}
		return k;
	}

	void erase(const T& val) {
		int k = lower_bound(val);
		if(k < size() && get(k) == val) {
			base::erase(root, k);
		}
	}

	void merge(ordered_set& other) {
		root = base::merge(root, other.root);
		other.root = nullptr;
	}

	std::pair<ordered_set, ordered_set> split(int k) {
		auto p = base::split(root, k);
		root = nullptr;
		return {ordered_set(p.first), ordered_set(p.second)};
	}

	std::tuple<ordered_set, ordered_set, ordered_set> split_range(int l, int r) {
		auto p = base::split_range(root, l, r);
		root = nullptr;
		return {ordered_set(std::get<0>(p)), ordered_set(std::get<1>(p)), ordered_set(std::get<2>(p))};
	}
};

template<class T, class Comp = std::less<T>>
struct ordered_multiset {
	using node_t = typename internal::node_t<T>;
	using base = internal::rbst_base<node_t, Comp>;

private:
	node_t* root = nullptr;
	ordered_multiset(node_t* v) : root(v) {}

public:
	ordered_multiset() {}
	ordered_multiset(const ordered_multiset& other) {
		clear();
		base::preorder(other.root, [&](node_t* v) {
			root = base::merge(root, new node_t(v->key));
		});
	}

	~ordered_multiset() { clear(); }

	int size() const { return base::size(root); }
	bool empty() const { return base::empty(root); }
	void clear() { base::clear(root); }

	int lower_bound(const T& val) const { return base::lower_bound(root, val); }
	int upper_bound(const T& val) const { return base::upper_bound(root, val); }

	T get(int k) {
		assert(0 <= k && k < size());
		return base::get(root, k);
	}

	int count(const T& val) const { return upper_bound(val) - lower_bound(val); }

	int insert(const T& val) {
		int k = lower_bound(val);
		base::insert(root, k, val);
		return k;
	}

	void erase(const T& val) {
		int k = lower_bound(val);
		if(k < size() && get(k) == val) {
			base::erase(root, k);
		}
	}

	void merge(ordered_multiset& other) {
		root = base::merge(root, other.root);
		other.root = nullptr;
	}

	std::pair<ordered_multiset, ordered_multiset> split(int k) {
		auto p = base::split(root, k);
		root = nullptr;
		return {ordered_multiset(p.first), ordered_multiset(p.second)};
	}

	std::tuple<ordered_multiset, ordered_multiset, ordered_multiset> split_range(int l, int r) {
		auto p = base::split_range(root, l, r);
		root = nullptr;
		return {ordered_multiset(std::get<0>(p)), ordered_multiset(std::get<1>(p)), ordered_multiset(std::get<2>(p))};
	}
};

} // namespace felix

#line 5 "test/data-structure/ordered-set/yosupo-Predecessor-Problem.test.cpp"
using namespace std;
using namespace felix;

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	int n, q;
	cin >> n >> q;
	ordered_set<int> tree;
	string s;
	cin >> s;
	for(int i = 0; i < n; i++) {
		if(s[i] == '1') {
			tree.insert(i);
		}
	}
	while(q--) {
		int type, x;
		cin >> type >> x;
		if(type == 0) {
			tree.insert(x);
		} else if(type == 1) {
			tree.erase(x);
		} else if(type == 2) {
			cout << tree.count(x) << "\n";
		} else if(type == 3) {
			int index = tree.lower_bound(x);
			int ans = -1;
			if(index < tree.size()) {
				ans = tree.get(index);
			}
			cout << ans << "\n";
		} else {
			int index = tree.upper_bound(x) - 1;
			int ans = -1;
			if(index >= 0) {
				ans = tree.get(index);
			}
			cout << ans << "\n";
		}
	}
	return 0;
}
Back to top page