首页 > 其他分享 >我的模板合集

我的模板合集

时间:2023-09-02 14:24:31浏览次数:34  
标签:index const cur 合集 key child data 模板

快速 IO 操作

quick_io.hpp

#include <cstdio>
#include <cstring>

template <const size_t _Size = 16>
class quick_io {
private:
	char buf_in[1 << _Size], buf_out[1 << _Size];
	size_t index_in, index_out;
	FILE *in, *out;

public:
	inline void flush_in() {
		fread(buf_in, sizeof(char), 1 << _Size, in), index_in = 0;
	}
	inline void flush_out() {
		fwrite(buf_out, index_out, 1, out), index_out = 0;
	}
	inline quick_io& operator>>(char& ch) {
		if (index_in == (1 << _Size)) flush_in();
		ch = buf_in[index_in++];
		return *this;
	}
	inline quick_io& operator>>(char* str) {
		size_t origin = strlen(str);
		char ch = 0;
		size_t len = 0;
		do {
			*this >> ch;
			if (!isgraph(ch)) break;
			str[len++] = ch;
		} while (true);
		if (len < origin)
			while (len < origin) str[len++] = 0;
		return *this;
	}
	template <typename T>
	inline quick_io& operator>>(T& value) {
		value = 0;
		short sign = 1;
		char ch = 0;
		do sign = ch == '-' ? -1 : sign, *this >> ch;
		while (ch < '0' || ch > '9');
		do value = (value << 3) + (value << 1) + ch - '0', *this >> ch;
		while ('0' <= ch && ch <= '9');
		value *= sign;
		return *this;
	}
	inline quick_io& operator<<(const char ch) {
		if (index_out == (1 << _Size)) flush_out();
		buf_out[index_out++] = ch;
		return *this;
	}
	inline quick_io& operator<<(const char* str) {
		size_t len = strlen(str);
		for (size_t i = 0; i < len; ++i) *this << str[i];
		return *this;
	}
	inline quick_io& operator<<(char* str) {
		size_t len = strlen(str);
		for (size_t i = 0; i < len; ++i) *this << str[i];
		return *this;
	}
	template <typename T>
	inline quick_io& operator<<(T value) {
		if (value < 0) *this << '-', value = -value;
		static size_t stack[50], dep = 0;
		do stack[++dep] = value % 10, value /= 10;
		while (value);
		do *this << (char)(stack[dep--] + '0');
		while (dep);
		return *this;
	}
	quick_io(FILE* in = stdin, FILE* out = stdout)
		: index_in(0), index_out(0), in(in), out(out) {}
	~quick_io() { flush_out(); }
};

example

#include "quick_io.hpp>"
quick_io<16> io;
int main() {
	int a, b;
	io >> a >> b << a + b << '\n';
	return 0;
}

线段树

传递函数指针的版本(Before C++ 20)

lazysegtree.hpp

#include <vector>

template <typename index_T, typename value_t, value_t (*opt)(value_t, value_t),
		  value_t (*e_val)(), typename tag_T,
		  value_t (*apply)(value_t, tag_T, index_T),
		  tag_T (*attach)(tag_T, tag_T), tag_T (*e_tag)()>
class LazySegmentTree {
private:
	index_T n;
	std::vector<value_t> val;
	std::vector<tag_T> tag;
	mutable std::vector<std::pair<index_T, index_T>> child;
	index_T root;
	const index_T no_child = 0;

	inline void new_node(index_T& index) {
		index = val.size();
		val.push_back(e_val());
		tag.push_back(e_tag());
		child.push_back(std::make_pair(no_child, no_child));
	}

	inline void push_up(const index_T index) {
		val[index] = opt(val[child[index].first], val[child[index].second]);
	}
	inline void push_down(const index_T index, const index_T size) {
		if (child[index].first == no_child) new_node(child[index].first);
		if (child[index].second == no_child) new_node(child[index].second);
		val[child[index].first] =
			apply(val[child[index].first], tag[index], size / 2);
		val[child[index].second] =
			apply(val[child[index].second], tag[index], size - size / 2);
		tag[child[index].first] = attach(tag[child[index].first], tag[index]);
		tag[child[index].second] = attach(tag[child[index].second], tag[index]);
		tag[index] = e_tag();
	}
	void set(const index_T _l, const index_T _r, const tag_T _tag,
			 const index_T l, const index_T r, const index_T index) {
		if (_l >= r || _r <= l) return;
		if (_l <= l && r <= _r) {
			val[index] = apply(val[index], _tag, r - l);
			tag[index] = attach(tag[index], _tag);
			return;
		}
		push_down(index, r - l);
		index_T mid = (l + r) >> 1;
		if (_l < mid) set(_l, _r, _tag, l, mid, child[index].first);
		if (_r >= mid) set(_l, _r, _tag, mid, r, child[index].second);
		push_up(index);
	}
	value_t get(const index_T _l, const index_T _r, const index_T l,
				const index_T r, const index_T index) {
		if (_l >= r || _r <= l) return e_val();
		if (_l <= l && r <= _r) return val[index];
		push_down(index, r - l);
		index_T mid = (l + r) >> 1;
		if (_l >= mid) return get(_l, _r, mid, r, child[index].second);
		if (_r < mid) return get(_l, _r, l, mid, child[index].first);
		return opt(get(_l, _r, l, mid, child[index].first),
				   get(_l, _r, mid, r, child[index].second));
	}

public:
	inline void set(const index_T _l, const index_T _r, const tag_T _tag) {
		set(_l, _r, _tag, 0, n, 0);
	}
	inline void set(const index_T _pos, const tag_T _tag) {
		set(_pos, _pos + 1, _tag, 0, n, 0);
	}
	inline value_t get(const index_T _l, const index_T _r) {
		return get(_l, _r, 0, n, 0);
	}
	inline value_t get(const index_T _pos) {
		return get(_pos, _pos + 1, 0, n, 0);
	}
	inline value_t get() { return val.front(); }
	LazySegmentTree(index_T n) : n(n) { new_node(root); }
};

example

P3372 Submission Record

#include <iostream>

#include "lazysegtree.hpp"

using i64 = long long;

i64 opt(i64 x, i64 y) { return x + y; }
i64 apply(i64 x, i64 y, int size) { return x + y * size; }
i64 attach(i64 x, i64 y) { return x + y; }
i64 e_val() { return 0ll; }
i64 e_tag() { return 0ll; }

int main() {
	int n, m;
	std::cin >> n >> m;

	LazySegmentTree<int, i64, opt, e_val, i64, apply, attach, e_tag> T(n);

	for (int i = 0; i < n; ++i) {
		int x;
		std::cin >> x;
		T.set(i, x);
	}

	for (int i = 0; i < m; ++i) {
		int opt, l, r;
		std::cin >> opt >> l >> r, --l;
		if (opt == 1) {
			i64 k;
			std::cin >> k;
			T.set(l, r, k);
		} else {
			std::cout << T.get(l, r) << '\n';
		}
	}

	return 0;
}

传递 lambda 表达式的版本(C++ 20)

lazysegtree_lambda.hpp

#include <vector>

template <typename index_T, typename value_t, typename tag_T, auto merge,
		  auto apply, auto attach, auto e_val, auto e_tag>
class LazySegmentTree {
private:
	index_T n;
	std::vector<value_t> val;
	std::vector<tag_T> tag;
	mutable std::vector<std::pair<index_T, index_T>> child;
	index_T root;
	const index_T no_child = 0;

	inline void new_node(index_T& index) {
		index = val.size();
		val.push_back(e_val());
		tag.push_back(e_tag());
		child.push_back(std::make_pair(no_child, no_child));
	}

	inline void push_up(const index_T index) {
		val[index] = merge(val[child[index].first], val[child[index].second]);
	}
	inline void push_down(const index_T index, const index_T size) {
		if (child[index].first == no_child) new_node(child[index].first);
		if (child[index].second == no_child) new_node(child[index].second);
		val[child[index].first] =
			apply(val[child[index].first], tag[index], size / 2);
		val[child[index].second] =
			apply(val[child[index].second], tag[index], size - size / 2);
		tag[child[index].first] = attach(tag[child[index].first], tag[index]);
		tag[child[index].second] = attach(tag[child[index].second], tag[index]);
		tag[index] = e_tag();
	}
	void set(const index_T _l, const index_T _r, const tag_T _tag,
			 const index_T l, const index_T r, const index_T index) {
		if (_l >= r || _r <= l) return;
		if (_l <= l && r <= _r) {
			val[index] = apply(val[index], _tag, r - l);
			tag[index] = attach(tag[index], _tag);
			return;
		}
		push_down(index, r - l);
		index_T mid = (l + r) >> 1;
		if (_l < mid) set(_l, _r, _tag, l, mid, child[index].first);
		if (_r >= mid) set(_l, _r, _tag, mid, r, child[index].second);
		push_up(index);
	}
	value_t get(const index_T _l, const index_T _r, const index_T l,
				const index_T r, const index_T index) {
		if (_l >= r || _r <= l) return e_val();
		if (_l <= l && r <= _r) return val[index];
		push_down(index, r - l);
		index_T mid = (l + r) >> 1;
		if (_l >= mid) return get(_l, _r, mid, r, child[index].second);
		if (_r < mid) return get(_l, _r, l, mid, child[index].first);
		return merge(get(_l, _r, l, mid, child[index].first),
					 get(_l, _r, mid, r, child[index].second));
	}

public:
	inline void set(const index_T _l, const index_T _r, const tag_T _tag) {
		set(_l, _r, _tag, 0, n, 0);
	}
	inline void set(const index_T _pos, const tag_T _tag) {
		set(_pos, _pos + 1, _tag, 0, n, 0);
	}
	inline value_t get(const index_T _l, const index_T _r) {
		return get(_l, _r, 0, n, 0);
	}
	inline value_t get(const index_T _pos) {
		return get(_pos, _pos + 1, 0, n, 0);
	}
	inline value_t get() { return val.front(); }
	LazySegmentTree(index_T n) : n(n) { new_node(root); }
};

example

P3372 Submission Record

#include "lazysegtree_lambda.hpp"

using i64 = long long;

int main() {
	int n, m;
	std::cin >> n >> m;

	LazySegmentTree<int, i64, i64, [](i64 a, i64 b) { return a + b; },
					[](i64 a, i64 b, int size) { return a + b * size; },
					[](i64 a, i64 b) { return a + b; }, []() { return 0ll; },
					[]() { return 0ll; }>
		T(n);

	for (int i = 0; i < n; ++i) {
		i64 x;
		std::cin >> x;
		T.set(i, x);
	}

	for (int i = 0; i < m; ++i) {
		int opt;
		std::cin >> opt;
		if (opt == 1) {
			int x, y, k;
			std::cin >> x >> y >> k;
			--x;
			T.set(x, y, k);
		} else {
			int x, y;
			std::cin >> x >> y;
			--x;
			std::cout << T.get(x, y) << '\n';
		}
	}
}

P2572 Submission Record

#include "lazysegtree_lambda.hpp"

struct Value {
	std::array<int, 2> num, pre, suf, bet;
	Value(std::array<int, 2> num = {0, 0}, std::array<int, 2> pre = {0, 0},
		  std::array<int, 2> suf = {0, 0}, std::array<int, 2> bet = {0, 0})
		: num(num), pre(pre), suf(suf), bet(bet) {}
};

#include <iostream>

int main() {
	int n, m;
	std::cin >> n >> m;
	LazySegmentTree<
		int, Value, short,
		[](Value ls, Value rs) {
			return Value(
				{ls.num[0] + rs.num[0], ls.num[1] + rs.num[1]},
				{ls.pre[0] + (ls.num[1] == 0 ? rs.pre[0] : 0),
				 ls.pre[1] + (ls.num[0] == 0 ? rs.pre[1] : 0)},
				{rs.suf[0] + (rs.num[1] == 0 ? ls.suf[0] : 0),
				 rs.suf[1] + (rs.num[0] == 0 ? ls.suf[1] : 0)},
				{std::max({ls.bet[0], rs.bet[0], ls.suf[0] + rs.pre[0]}),
				 std::max({ls.bet[1], rs.bet[1], ls.suf[1] + rs.pre[1]})});
		},
		[](Value x, short y, int size) {
			if (y == -1) return x;
			if (y == 0)
				return Value({size, 0}, {size, 0}, {size, 0}, {size, 0});
			if (y == 1)
				return Value({0, size}, {0, size}, {0, size}, {0, size});
			std::swap(x.num[0], x.num[1]);
			std::swap(x.pre[0], x.pre[1]);
			std::swap(x.suf[0], x.suf[1]);
			std::swap(x.bet[0], x.bet[1]);
			return x;
		},
		[](short tag_old, short tag_new) {
			if (tag_new == -1) return tag_old;
			if (tag_new == 0) return (short)0;
			if (tag_new == 1) return (short)1;
			if (tag_old == 0 || tag_old == 1) return (short)(tag_old ^ 1);
			return tag_old == 2 ? (short)(-1) : (short)2;
		},
		[]() { return Value(); }, []() { return (short)-1; }>
		T(n);
	for (int i = 0; i < n; ++i) {
		int x;
		std::cin >> x;
		T.set(i, (short)x);
	}
	for (int i = 0; i < m; ++i) {
		int opt, l, r;
		std::cin >> opt >> l >> r;
		++r;
		if (opt == 0) {
			T.set(l, r, 0);
		} else if (opt == 1) {
			T.set(l, r, 1);
		} else if (opt == 2) {
			T.set(l, r, 2);
		} else if (opt == 3) {
			std::cout << T.get(l, r).num[1] << '\n';
		} else if (opt == 4) {
			std::cout << T.get(l, r).bet[1] << '\n';
		} else {
			exit(1);
		}
	}

	return 0;
}

Dinic 网络流

networkflow.hpp

#include <queue>
#include <vector>

struct Edge {
	int to, nxt;
	Edge(const int to = 0, const int nxt = -1) : to(to), nxt(nxt) {}
};

template <typename T>
struct Flow : public Edge {
	T capicity, flow;
	Flow(const int to = 0, const int nxt = -1, const T capicity = 0, const T flow = 0)
		: Edge(to, nxt), capicity(capicity), flow(flow) {}
};

class Graph {
public:
	int n, m;
	std::vector<int> head;
	int cnt;
	Graph(int n, int m) : n(n), m(m), head(n, -1), cnt(-1) {}
};

template <typename T>
class NetworkFlow : public Graph {
public:
	int s, t;
	T inf;
	std::vector<int> dep, cur;

	std::vector<Flow<T>> ed;

	inline void add_edge(const int from = 0, const int to = 0, const T capicity = 0, const T flow = 0) {
		ed[++cnt].to = to, ed[cnt].nxt = head[from], head[from] = cnt, ed[cnt].capicity = capicity,
		ed[cnt].flow = flow;
	}

	NetworkFlow(int n, int m, int s, int t, T inf)
		: Graph(n, m), s(s), t(t), inf(inf), dep(n), cur(n, -1), ed(m) {}

private:
	auto bfs(int s, int t) {
		std::queue<int> q;
		while (q.size()) q.pop();
		dep.assign(n, 0);
		dep[s] = 1;
		q.push(s);
		while (q.size()) {
			int x = q.front();
			q.pop();
			for (int i = head[x]; ~i; i = ed[i].nxt) {
				if ((!dep[ed[i].to]) && (ed[i].capicity > ed[i].flow)) {
					dep[ed[i].to] = dep[x] + 1;
					q.push(ed[i].to);
				}
			}
		}
		return dep[t] > 0;
	}

	T dfs(int x, int t, T flow) {
		if (x == t || (!flow)) return flow;
		T ret = 0;
		for (int& i = cur[x]; ~i; i = ed[i].nxt) {
			T d;
			if ((dep[ed[i].to] == dep[x] + 1) &&
				(d = dfs(ed[i].to, t, std::min(flow - ret, ed[i].capicity - ed[i].flow)))) {
				ret += d;
				ed[i].flow += d;
				ed[i ^ 1].flow -= d;
				if (ret == flow) return ret;
			}
		}
		return ret;
	}

public:
	T dinic() {
		T max_flow = 0;
		while (bfs(s, t)) {
			cur = head;
			max_flow += dfs(s, t, inf);
		}
		return max_flow;
	}
};

并查集

dsu.hpp

#include <vector>

template <typename T>
class Dsu {
private:
	T n;
	std::vector<T> fa, siz;

public:
	Dsu(T n) : n(n), fa(n), siz(n) {
		for (T i = 0; i < n; ++i) fa[i] = i, siz[i] = 1;
	}
	bool empty() { return n == 0; }
	T size() { return n; }
	void reset() {
		for (T i = 0; i < n; ++i) fa[i] = i, siz[i] = 1;
	}
	void resize(T _n) : n(_n) { reset(); }
	T father(T x) { return fa[x] == x ? x : fa[x] = father(fa[x]); }
	bool is_root(T x) { return father(x) == x; }
	bool merge(T _u, T _v) {
		_u = father(_u), _v = father(_v);
		if (_u == _v) return false;
		if (siz[_u] < siz[_v]) std::swap(_u, _v);
		siz[fa[_u] = _v] += siz[_u];
		return true;
	}
	bool check(T _u, T _v) { return father(_u) == father(_v); }
	T size(T x) { return siz[father(x)]; }
};

BST

bst.hpp

#include <queue>
#include <tuple>
#include <utility>
#include <vector>

template <typename value_T, typename index_T>
class Splay {
	const int not_exist = 0;

public:
	index_T root;

private:
	enum child_t { left = false, right = true };
	struct Node {
		value_T key;
		index_T size, count;
		index_T child[2];
		index_T parent;
		Node(const value_T key = value_T())
			: key(key), size(0), count(0), parent(not_exist) {
			child[left] = child[right] = not_exist;
		}
	};

	std::vector<Node> data;
	std::queue<index_T> bin;

	void maintain(index_T index) {
		if (index == not_exist) return;
		data[index].size = data[data[index].child[left]].size +
						   data[data[index].child[right]].size +
						   data[index].count;
	}

	child_t identify(index_T index) {
		return data[data[index].parent].child[right] == index ? right : left;
	}

	void clear(index_T index) {
		data[index] = Node();
		bin.push(index);
	}

	void rotate(index_T index) {
		int parent = data[index].parent;
		int grand = data[parent].parent;
		child_t type = identify(index);
		data[parent].child[type] = data[index].child[type ^ 1];
		if (data[index].child[type ^ 1])
			data[data[index].child[type ^ 1]].parent = parent;
		data[index].child[type ^ 1] = parent;
		if (grand) data[grand].child[identify(parent)] = index;
		data[index].parent = grand;
		data[parent].parent = index;
		maintain(parent), maintain(index);
	}

	void splay(index_T index) {
		for (index_T cur = data[index].parent; cur = data[index].parent, cur;
			 rotate(index)) {
			if (data[cur].parent != not_exist)
				rotate(identify(index) == identify(cur) ? cur : index);
		}
		root = index;
	}

	index_T new_node(value_T key) {
		index_T index;
		if (!bin.empty()) {
			index = bin.front();
			bin.pop();
		} else {
			index = data.size();
			data.push_back(Node());
		}
		data[index].key = key;
		data[index].count = 1;
		data[index].size = 1;
		return index;
	}

public:
	void insert(value_T key) {
		if (root == not_exist) {
			root = new_node(key);
			return;
		}
		index_T cur = root, parent = not_exist;
		while (cur != not_exist && data[cur].key != key) {
			parent = cur, cur = data[cur].child[data[cur].key < key];
		}
		if (cur == not_exist) {
			cur = new_node(key);
			data[cur].parent = parent;
			data[parent].child[data[parent].key < key] = cur;
		} else
			++data[cur].count;
		maintain(cur);
		maintain(parent);
		splay(cur);
	}

	index_T rank(value_T key) {
		index_T res = 0, cur = root;
		while (key != data[cur].key) {
			if (key < data[cur].key) {
				cur = data[cur].child[left];
			} else {
				res += data[data[cur].child[left]].size + data[cur].count;
				cur = data[cur].child[right];
			}
		}
		res += data[data[cur].child[left]].size;
		splay(cur);
		return res + 1;
	}

	value_T kth(index_T rank) {
		index_T cur = root;
		while (true) {
			if (data[cur].child[left] != not_exist &&
				rank <= data[data[cur].child[left]].size) {
				cur = data[cur].child[left];
			} else if (rank >
					   data[data[cur].child[left]].size + data[cur].count) {
				rank -= data[cur].count + data[data[cur].child[left]].size;
				cur = data[cur].child[right];
			} else {
				splay(cur);
				return data[cur].key;
			}
		}
	}

private:
	index_T prefix() {
		index_T cur = data[root].child[left];
		if (cur == not_exist) return cur;
		while (data[cur].child[right] != not_exist)
			cur = data[cur].child[right];
		splay(cur);
		return cur;
	}
	index_T suffix() {
		index_T cur = data[root].child[right];
		if (cur == not_exist) return cur;
		while (data[cur].child[left]) cur = data[cur].child[left];
		splay(cur);
		return cur;
	}

public:
	void erase(int k) {
		rank(k);
		if (data[root].count > 1) {
			--data[root].count;
			maintain(root);
			return;
		}
		if (data[root].child[left] == not_exist &&
			data[root].child[right] == not_exist) {
			clear(root);
			root = not_exist;
			return;
		}
		if (data[root].child[left] == not_exist ||
			data[root].child[right] == not_exist) {
			index_T cur = root;
			root = data[root].child[right] + data[root].child[left];
			data[root].parent = not_exist;
			clear(cur);
			return;
		}
		index_T cur = root, x = prefix();
		data[data[cur].child[right]].parent = x;
		data[x].child[right] = data[cur].child[right];
		clear(cur);
		maintain(root);
	}

	value_T prefix(value_T key) {
		insert(key);
		index_T index = prefix();
		erase(key);
		return data[index].key;
	}
	value_T suffix(value_T key) {
		insert(key);
		index_T index = suffix();
		erase(key);
		return data[index].key;
	}
	Splay() {
		root = new_node(value_T()), data[root].size = data[root].count = 0;
	}
};

template <typename index_T, typename value_T, index_T (*rand)()>
class FHQTreap {
private:
	enum child_t { left = false, right = true };
	struct Node {
		Node* child[2];
		value_T key;
		index_T value;
		index_T size, count;

		Node(value_T key) : key(key), size(1), count(1) {
			child[left] = child[right] = nullptr;
			value = rand();
		}
		Node(Node* _node) {
			child[left] = _node->child[left],
			child[right] = _node->child[right];
			key = _node->key, value = _node->value;
			size = _node->size, count = _node->count;
		}

		void maintain() {
			size = count;
			if (child[left] != nullptr) size += child[left]->size;
			if (child[right] != nullptr) size += child[right]->size;
		}
	};

public:
	Node* root;

private:
	std::pair<Node*, Node*> split_by_key(Node* cur, value_T key) {
		if (cur == nullptr) return std::make_pair(nullptr, nullptr);
		if (cur->key <= key) {
			std::pair<Node*, Node*> res = split_by_key(cur->child[right], key);
			cur->child[right] = res.first, cur->maintain();
			return std::make_pair(cur, res.second);
		} else {
			std::pair<Node*, Node*> res = split_by_key(cur->child[left], key);
			cur->child[left] = res.second, cur->maintain();
			return std::make_pair(res.first, cur);
		}
	}

	std::tuple<Node*, Node*, Node*> split_by_rank(Node* cur, index_T rank) {
		if (cur == nullptr) return std::make_tuple(nullptr, nullptr, nullptr);
		index_T left_size =
			cur->child[left] == nullptr ? 0 : cur->child[left]->size;
		if (rank <= left_size) {
			Node *l, *mid, *r;
			std::tie(l, mid, r) = split_by_rank(cur->child[left], rank);
			cur->child[left] = r, cur->maintain();
			return std::make_tuple(l, mid, cur);
		} else if (rank <= left_size + cur->count) {
			Node *l = cur->child[left], *r = cur->child[right];
			cur->child[left] = cur->child[right] = nullptr;
			return std::make_tuple(l, cur, r);
		} else {
			Node *l, *mid, *r;
			std::tie(l, mid, r) =
				split_by_rank(cur->child[right], rank - left_size - cur->count);
			cur->child[right] = l, cur->maintain();
			return std::make_tuple(cur, mid, r);
		}
	}

	Node* merge(Node* u, Node* v) {
		if (u == nullptr && v == nullptr) return nullptr;
		if (u == nullptr || v == nullptr) return u == nullptr ? v : u;
		if (u->value < v->value)
			return u->child[right] = merge(u->child[right], v), u->maintain(),
				   u;
		else
			return v->child[left] = merge(u, v->child[left]), v->maintain(), v;
	}

public:
	void insert(const value_T key) {
		std::pair<Node*, Node*> u = split_by_key(root, key);
		std::pair<Node*, Node*> v = split_by_key(u.first, key - 1);
		Node* cur;
		if (v.second == nullptr)
			cur = new Node(key);
		else
			++v.second->count, v.second->maintain();
		root = merge(merge(v.first, v.second == nullptr ? cur : v.second),
					 u.second);
	}

	void erase(const value_T key) {
		std::pair<Node*, Node*> u = split_by_key(root, key);
		std::pair<Node*, Node*> v = split_by_key(u.first, key - 1);
		if (v.second->count > 1)
			--v.second->count, v.second->maintain(),
				v.first = merge(v.first, v.second);
		else {
			if (u.first == v.second) u.first = nullptr;
			delete v.second;
			v.second = nullptr;
		}
		root = merge(v.first, u.second);
	}

	index_T rank(Node* cur, const value_T key) {
		std::pair<Node*, Node*> res = split_by_key(cur, key - 1);
		index_T rank = (res.first == nullptr ? 0 : res.first->size) + 1;
		root = merge(res.first, res.second);
		return rank;
	}

	value_T kth(Node* cur, const index_T rank) {
		Node *l, *mid, *r;
		std::tie(l, mid, r) = split_by_rank(cur, rank);
		value_T key = mid->key;
		root = merge(merge(l, mid), r);
		return key;
	}

	value_T prefix(value_T key) {
		std::pair<Node*, Node*> temp = split_by_key(root, key - 1);
		value_T ret = kth(temp.first, temp.first->size);
		root = merge(temp.first, temp.second);
		return ret;
	}
	value_T suffix(value_T key) {
		std::pair<Node*, Node*> temp = split_by_key(root, key);
		value_T ret = kth(temp.second, 1);
		root = merge(temp.first, temp.second);
		return ret;
	}

public:
	FHQTreap() : root(nullptr){};
	~FHQTreap() { delete root; }
};

标签:index,const,cur,合集,key,child,data,模板
From: https://www.cnblogs.com/escap1st/p/17673626.html

相关文章

  • mybatis中的UserMapper.xml模板与测试mybatis的代码
    2023-09-02UserMapper.xml模板<?xmlversion="1.0"encoding="UTF-8"?><!DOCTYPEmapperPUBLIC"-//mybatis.org//DTDMapper3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mappe......
  • mybatis-config.xml模板
    2023-09-02<?xmlversion="1.0"encoding="UTF-8"?><!DOCTYPEconfigurationPUBLIC"-//mybatis.org//DTDConfig3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration>......
  • 日志logback.xml配置文件的模板与导入的依赖
    2023-09-02依赖的jar包<dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.20</version></dependency><dependency><groupId>ch.qos.logback</g......
  • 关于SpringBoot中引入html模板的问题的解决(基础)
    问题描述将相关的文件放置到resources/static文件夹目录下面,文件路径正确,但是一直应用不了问题解决原来是在引用的时候,需要在每个文件前面加上一个斜杠——/,这样就解决啦!......
  • 备战金九银十秋招面试,Android面试高频题合集,赶快收藏起来
    前言现在面试可以说是我们最常挂在嘴边的一个话题了,面试题、面试宝典、面试手册......各种Android面试题一搜一大把,根本看不完,而且现在的面试资料也都还可以,然后就放进了收藏夹吃灰,真到面试的时候,又被面试官问得脚趾扣地。人都是不满足于现状的,现在15K的薪资,下一份就想拿40K,甚至想......
  • C++模板
    一、类型信息运算符typeid在C++中typeid可以获取数据的类型,但是需要加头文件typeinfofind/usr/include-nametypeinfotypeid是运算符,执行运算符函数,执行的返回类型是type_info类类型对象type_info中有个name的成员函数type_info中还重载了==运算符,可以直接比较......
  • jiangly算法模板收集
    目录数据结构树状数组并查集线段树其一其二其三懒标记线段树取模类(新版)取模类(旧版)树链剖分Splay其他二叉树其一其二分数四则运算数论欧拉筛组合数多项式相关几何图论(有向图)强连通分量缩点(无向图)求解割边、割边缩点一般图最大匹配(带花树算法)【久远】最大流费用流2-Sat【久远】字符......
  • Linux组件安装部署手册模板
    Linux系统-部署-运维系列导航 背景说明组件安装步骤是基本通用的,大部分组件安装都需要经过一些必须的流程,才能成为有效的服务。 本文以Linux(CentOS7)系统为基础介绍,其他操作系统原理一样,只是部分操作的具体执行方式需要根据操作系统调整。  根据经验总结,组件安装一般都......
  • 创意无限!AI绘画、ChatGPT、AIGC工具合集,让你的创作梦想成真
    推荐阅读项目实战:AI文本OCR识别最佳实践AIGamma一键生成PPT工具直达链接玩转cloudStudio在线编码神器玩转GPUAI绘画、AI讲话、翻译,GPU点亮AI想象空间资源分享史上最全文档AI绘画stablediffusion资料分享AI绘画stablediffusionMidjourney官方GPT文档AIGC百科全书......
  • 【专题】2022年中国母婴行业新媒体营销价值研究报告PDF合集分享(附原数据表)
    原文链接:https://tecdat.cn/?p=33528报告合集显示,由于新生儿出生率下降,母婴行业进入了存量时代。在这一背景下,抖音电商成为越来越多消费者的选择,尤其是24-40岁的三四线城市女性。这一消费群体更倾向于在线上购买,给母婴行业的线上销售带来了巨大的机遇。阅读原文,获取专题报告合集......