This documentation is automatically generated by competitive-verifier/competitive-verifier
#include "cp-algo/structures/treap.hpp"#ifndef CP_ALGO_STRUCTURES_TREAP_HPP
#define CP_ALGO_STRUCTURES_TREAP_HPP
#include "../util/big_alloc.hpp"
#include "../random/rng.hpp"
#include "treap/common.hpp"
#include <array>
namespace cp_algo::structures::treap {
template<typename meta>
struct node {
using treap = node*;
meta _meta;
int prior = (int)random::rng();
size_t size = 1;
treap children[2] = {nullptr, nullptr};
enum subtree {L, R};
node() {}
node(meta _meta): _meta(_meta) {}
node(meta _meta, int prior): _meta(_meta), prior(prior) {}
static treap make_treap(auto...args) {
return new node(args...);
}
treap pull() {
_meta.pull(children[L], children[R]);
size = 1 + _safe(children[L], size) + _safe(children[R], size);
return this;
}
treap push() {
_meta.push(children[L], children[R]);
return this;
}
// set i-th child and pull metadata
treap set(subtree i, treap t) {
children[i] = t;
return pull();
}
// push changes and detach the i-th child
treap cut(subtree i) {
return children[i];
}
static treap merge(treap A, treap B) {
if(!_safe(A, push()) || !_safe(B, push())) {
return A ? A : B;
} else if(A->prior < B->prior) {
return A->set(R, merge(A->cut(R), B));
} else {
return B->set(L, merge(A, B->cut(L)));
}
}
// return {L, R}, where |L|=k or L=A when |A| < k
static std::array<treap, 2> split(treap A, size_t k) {
if(!_safe(A, push())) {
return {nullptr, nullptr};
} else if(_safe(A->children[L], size) >= k) {
auto [split_L, split_R] = split(A->cut(L), k);
return {split_L, A->set(L, split_R)};
} else {
k -= _safe(A->children[L], size) + 1;
auto [split_L, split_R] = split(A->cut(R), k);
return {A->set(R, split_L), split_R};
}
}
static void exec_on_segment(treap &A, size_t l, size_t r, auto func) {
auto [LM, R] = split(A, r);
auto [L, M] = split(LM, l);
func(M);
A = merge(L, merge(M, R));
}
static void insert(treap &A, size_t pos, treap t) {
auto [L, R] = split(A, pos);
A = merge(L, merge(t, R));
}
static void erase(treap &A, size_t pos) {
auto [L, MR] = split(A, pos);
auto [M, R] = split(MR, 1);
delete M;
A = merge(L, R);
}
static void exec_on_each(treap &A, auto func) {
if(A) {
exec_on_each(A->children[L], func);
func(A);
exec_on_each(A->children[R], func);
}
}
treap pull_all() {
_safe(children[L], pull_all());
_safe(children[R], pull_all());
return pull();
}
treap push_all() {
push();
_safe(children[L], push_all());
_safe(children[R], push_all());
return this;
}
static treap build(auto const& nodes) {
big_vector<treap> st;
for(auto cur: nodes) {
while(st.size() >= 2 && st[st.size() - 2]->prior > cur->prior) {
st.pop_back();
}
if(!st.empty() && st.back()->prior > cur->prior) {
cur->set(L, st.back());
st.pop_back();
}
if(!st.empty() && st.back()->prior < cur->prior) {
st.back()->set(R, cur);
}
st.push_back(cur);
}
return st.empty() ? nullptr : st[0]->pull_all();
}
};
struct null_meta {
void pull(auto const, auto const) {}
void push(auto&, auto&) {}
};
}
#endif // CP_ALGO_STRUCTURES_TREAP_HPP
#line 1 "cp-algo/structures/treap.hpp"
#line 1 "cp-algo/util/big_alloc.hpp"
#include <set>
#include <map>
#include <deque>
#include <stack>
#include <queue>
#include <vector>
#include <string>
#include <cstddef>
#include <bit>
#include <iostream>
#include <forward_list>
// Single macro to detect POSIX platforms (Linux, Unix, macOS)
#if defined(__linux__) || defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
#define CP_ALGO_USE_MMAP 1
#include <sys/mman.h>
#else
#define CP_ALGO_USE_MMAP 0
#endif
namespace cp_algo {
template<typename T, size_t Align = 32>
class big_alloc {
static_assert(Align >= alignof(void*), "Align must be at least pointer-size");
static_assert(std::has_single_bit(Align), "Align must be a power of two");
public:
using value_type = T;
template<class U>
struct rebind {
using other = big_alloc<U, Align>;
};
constexpr bool operator==(const big_alloc&) const = default;
big_alloc() noexcept = default;
template<typename U, std::size_t A>
big_alloc(const big_alloc<U, A>&) noexcept {}
[[nodiscard]] T* allocate(std::size_t n) {
std::size_t padded = round_up(n * sizeof(T));
std::size_t align = std::max<std::size_t>(alignof(T), Align);
#if CP_ALGO_USE_MMAP
if(padded >= MEGABYTE) {
void* raw = mmap(nullptr, padded, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
madvise(raw, padded, MADV_HUGEPAGE);
return static_cast<T*>(raw);
}
#endif
return static_cast<T*>(::operator new(padded, std::align_val_t(align)));
}
void deallocate(T* p, std::size_t n) noexcept {
if(!p) {
return;
}
std::size_t padded = round_up(n * sizeof(T));
std::size_t align = std::max<std::size_t>(alignof(T), Align);
#if CP_ALGO_USE_MMAP
if(padded >= MEGABYTE) {
munmap(p, padded);
return;
}
#endif
::operator delete(p, padded, std::align_val_t(align));
}
private:
static constexpr std::size_t MEGABYTE = 1 << 20;
static constexpr std::size_t round_up(std::size_t x) noexcept {
return (x + Align - 1) / Align * Align;
}
};
template<typename T>
using big_vector = std::vector<T, big_alloc<T>>;
template<typename T>
using big_basic_string = std::basic_string<T, std::char_traits<T>, big_alloc<T>>;
template<typename T>
using big_deque = std::deque<T, big_alloc<T>>;
template<typename T>
using big_stack = std::stack<T, big_deque<T>>;
template<typename T>
using big_queue = std::queue<T, big_deque<T>>;
template<typename T>
using big_priority_queue = std::priority_queue<T, big_vector<T>>;
template<typename T>
using big_forward_list = std::forward_list<T, big_alloc<T>>;
using big_string = big_basic_string<char>;
template<typename Key, typename Value, typename Compare = std::less<Key>>
using big_map = std::map<Key, Value, Compare, big_alloc<std::pair<const Key, Value>>>;
template<typename T, typename Compare = std::less<T>>
using big_multiset = std::multiset<T, Compare, big_alloc<T>>;
template<typename T, typename Compare = std::less<T>>
using big_set = std::set<T, Compare, big_alloc<T>>;
}
#line 1 "cp-algo/random/rng.hpp"
#include <chrono>
#include <random>
namespace cp_algo::random {
std::mt19937_64 gen(
std::chrono::steady_clock::now().time_since_epoch().count()
);
uint64_t rng() {
return gen();
}
}
#line 1 "cp-algo/structures/treap/common.hpp"
#define _safe(t, op) (t ? t->op : typename std::remove_reference_t<decltype(t->op)>())
#line 6 "cp-algo/structures/treap.hpp"
#include <array>
namespace cp_algo::structures::treap {
template<typename meta>
struct node {
using treap = node*;
meta _meta;
int prior = (int)random::rng();
size_t size = 1;
treap children[2] = {nullptr, nullptr};
enum subtree {L, R};
node() {}
node(meta _meta): _meta(_meta) {}
node(meta _meta, int prior): _meta(_meta), prior(prior) {}
static treap make_treap(auto...args) {
return new node(args...);
}
treap pull() {
_meta.pull(children[L], children[R]);
size = 1 + _safe(children[L], size) + _safe(children[R], size);
return this;
}
treap push() {
_meta.push(children[L], children[R]);
return this;
}
// set i-th child and pull metadata
treap set(subtree i, treap t) {
children[i] = t;
return pull();
}
// push changes and detach the i-th child
treap cut(subtree i) {
return children[i];
}
static treap merge(treap A, treap B) {
if(!_safe(A, push()) || !_safe(B, push())) {
return A ? A : B;
} else if(A->prior < B->prior) {
return A->set(R, merge(A->cut(R), B));
} else {
return B->set(L, merge(A, B->cut(L)));
}
}
// return {L, R}, where |L|=k or L=A when |A| < k
static std::array<treap, 2> split(treap A, size_t k) {
if(!_safe(A, push())) {
return {nullptr, nullptr};
} else if(_safe(A->children[L], size) >= k) {
auto [split_L, split_R] = split(A->cut(L), k);
return {split_L, A->set(L, split_R)};
} else {
k -= _safe(A->children[L], size) + 1;
auto [split_L, split_R] = split(A->cut(R), k);
return {A->set(R, split_L), split_R};
}
}
static void exec_on_segment(treap &A, size_t l, size_t r, auto func) {
auto [LM, R] = split(A, r);
auto [L, M] = split(LM, l);
func(M);
A = merge(L, merge(M, R));
}
static void insert(treap &A, size_t pos, treap t) {
auto [L, R] = split(A, pos);
A = merge(L, merge(t, R));
}
static void erase(treap &A, size_t pos) {
auto [L, MR] = split(A, pos);
auto [M, R] = split(MR, 1);
delete M;
A = merge(L, R);
}
static void exec_on_each(treap &A, auto func) {
if(A) {
exec_on_each(A->children[L], func);
func(A);
exec_on_each(A->children[R], func);
}
}
treap pull_all() {
_safe(children[L], pull_all());
_safe(children[R], pull_all());
return pull();
}
treap push_all() {
push();
_safe(children[L], push_all());
_safe(children[R], push_all());
return this;
}
static treap build(auto const& nodes) {
big_vector<treap> st;
for(auto cur: nodes) {
while(st.size() >= 2 && st[st.size() - 2]->prior > cur->prior) {
st.pop_back();
}
if(!st.empty() && st.back()->prior > cur->prior) {
cur->set(L, st.back());
st.pop_back();
}
if(!st.empty() && st.back()->prior < cur->prior) {
st.back()->set(R, cur);
}
st.push_back(cur);
}
return st.empty() ? nullptr : st[0]->pull_all();
}
};
struct null_meta {
void pull(auto const, auto const) {}
void push(auto&, auto&) {}
};
}
#ifndef CP_ALGO_STRUCTURES_TREAP_HPP
#define CP_ALGO_STRUCTURES_TREAP_HPP
#include "../util/big_alloc.hpp"
#include "../random/rng.hpp"
#include "treap/common.hpp"
#include <array>
namespace cp_algo::structures::treap{ template<typename meta> struct node{ using treap=node*; meta _meta; int prior=(int)random::rng(); size_t size=1; treap children[2] ={nullptr,nullptr}; enum subtree{L,R}; node(){} node(meta _meta):_meta(_meta){} node(meta _meta,int prior):_meta(_meta),prior(prior){} static treap make_treap(auto...args){ return new node(args...); } treap pull(){ _meta.pull(children[L],children[R]); size=1+_safe(children[L],size)+_safe(children[R],size); return this; } treap push(){ _meta.push(children[L],children[R]); return this; } treap set(subtree i,treap t){ children[i] =t; return pull(); } treap cut(subtree i){ return children[i]; } static treap merge(treap A,treap B){ if(!_safe(A,push())|| !_safe(B,push())){ return A?A:B; }else if(A->prior<B->prior){ return A->set(R,merge(A->cut(R),B)); }else{ return B->set(L,merge(A,B->cut(L))); } } static std::array<treap,2>split(treap A,size_t k){ if(!_safe(A,push())){ return{nullptr,nullptr}; }else if(_safe(A->children[L],size)>=k){ auto[split_L,split_R] =split(A->cut(L),k); return{split_L,A->set(L,split_R)}; }else{ k-=_safe(A->children[L],size)+1; auto[split_L,split_R] =split(A->cut(R),k); return{A->set(R,split_L),split_R}; } } static void exec_on_segment(treap&A,size_t l,size_t r,auto func){ auto[LM,R] =split(A,r); auto[L,M] =split(LM,l); func(M); A=merge(L,merge(M,R)); } static void insert(treap&A,size_t pos,treap t){ auto[L,R] =split(A,pos); A=merge(L,merge(t,R)); } static void erase(treap&A,size_t pos){ auto[L,MR] =split(A,pos); auto[M,R] =split(MR,1); delete M; A=merge(L,R); } static void exec_on_each(treap&A,auto func){ if(A){ exec_on_each(A->children[L],func); func(A); exec_on_each(A->children[R],func); } } treap pull_all(){ _safe(children[L],pull_all()); _safe(children[R],pull_all()); return pull(); } treap push_all(){ push(); _safe(children[L],push_all()); _safe(children[R],push_all()); return this; } static treap build(auto const&nodes){ big_vector<treap>st; for(auto cur:nodes){ while(st.size()>=2&&st[st.size()-2]->prior>cur->prior){ st.pop_back(); } if(!st.empty()&&st.back()->prior>cur->prior){ cur->set(L,st.back()); st.pop_back(); } if(!st.empty()&&st.back()->prior<cur->prior){ st.back()->set(R,cur); } st.push_back(cur); } return st.empty()?nullptr:st[0]->pull_all(); } }; struct null_meta{ void pull(auto const,auto const){} void push(auto&,auto&){} }; }
#endif
#line 1 "cp-algo/structures/treap.hpp"
#line 1 "cp-algo/util/big_alloc.hpp"
#include <set>
#include <map>
#include <deque>
#include <stack>
#include <queue>
#include <vector>
#include <string>
#include <cstddef>
#include <bit>
#include <iostream>
#include <forward_list>
#if defined(__linux__) || defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
#define CP_ALGO_USE_MMAP 1
#include <sys/mman.h>
#else
#define CP_ALGO_USE_MMAP 0
#endif
namespace cp_algo{ template<typename T,size_t Align=32> class big_alloc{ static_assert(Align>=alignof(void*),"Align must be at least pointer-size"); static_assert(std::has_single_bit(Align),"Align must be a power of two"); public: using value_type=T; template<class U> struct rebind{ using other=big_alloc<U,Align>; }; constexpr bool operator==(const big_alloc&)const=default; big_alloc()noexcept=default; template<typename U,std::size_t A> big_alloc(const big_alloc<U,A>&)noexcept{} [[nodiscard]]T*allocate(std::size_t n){ std::size_t padded=round_up(n*sizeof(T)); std::size_t align=std::max<std::size_t>(alignof(T),Align);
#if CP_ALGO_USE_MMAP
if(padded>=MEGABYTE){ void*raw=mmap(nullptr,padded,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0); madvise(raw,padded,MADV_HUGEPAGE); return static_cast<T*>(raw); }
#endif
return static_cast<T*>(::operator new(padded,std::align_val_t(align))); } void deallocate(T*p,std::size_t n)noexcept{ if(!p){ return; } std::size_t padded=round_up(n*sizeof(T)); std::size_t align=std::max<std::size_t>(alignof(T),Align);
#if CP_ALGO_USE_MMAP
if(padded>=MEGABYTE){ munmap(p,padded); return; }
#endif
::operator delete(p,padded,std::align_val_t(align)); } private: static constexpr std::size_t MEGABYTE=1<<20; static constexpr std::size_t round_up(std::size_t x)noexcept{ return(x+Align-1)/Align*Align; } }; template<typename T> using big_vector=std::vector<T,big_alloc<T>>; template<typename T> using big_basic_string=std::basic_string<T,std::char_traits<T>,big_alloc<T>>; template<typename T> using big_deque=std::deque<T,big_alloc<T>>; template<typename T> using big_stack=std::stack<T,big_deque<T>>; template<typename T> using big_queue=std::queue<T,big_deque<T>>; template<typename T> using big_priority_queue=std::priority_queue<T,big_vector<T>>; template<typename T> using big_forward_list=std::forward_list<T,big_alloc<T>>; using big_string=big_basic_string<char>; template<typename Key,typename Value,typename Compare=std::less<Key>> using big_map=std::map<Key,Value,Compare,big_alloc<std::pair<const Key,Value>>>; template<typename T,typename Compare=std::less<T>> using big_multiset=std::multiset<T,Compare,big_alloc<T>>; template<typename T,typename Compare=std::less<T>> using big_set=std::set<T,Compare,big_alloc<T>>; }
#line 1 "cp-algo/random/rng.hpp"
#include <chrono>
#include <random>
namespace cp_algo::random{ std::mt19937_64 gen( std::chrono::steady_clock::now().time_since_epoch().count() ); uint64_t rng(){ return gen(); } }
#line 1 "cp-algo/structures/treap/common.hpp"
#define _safe(t, op) (t ? t->op : typename std::remove_reference_t<decltype(t->op)>())
#line 6 "cp-algo/structures/treap.hpp"
#include <array>
namespace cp_algo::structures::treap{ template<typename meta> struct node{ using treap=node*; meta _meta; int prior=(int)random::rng(); size_t size=1; treap children[2] ={nullptr,nullptr}; enum subtree{L,R}; node(){} node(meta _meta):_meta(_meta){} node(meta _meta,int prior):_meta(_meta),prior(prior){} static treap make_treap(auto...args){ return new node(args...); } treap pull(){ _meta.pull(children[L],children[R]); size=1+_safe(children[L],size)+_safe(children[R],size); return this; } treap push(){ _meta.push(children[L],children[R]); return this; } treap set(subtree i,treap t){ children[i] =t; return pull(); } treap cut(subtree i){ return children[i]; } static treap merge(treap A,treap B){ if(!_safe(A,push())|| !_safe(B,push())){ return A?A:B; }else if(A->prior<B->prior){ return A->set(R,merge(A->cut(R),B)); }else{ return B->set(L,merge(A,B->cut(L))); } } static std::array<treap,2>split(treap A,size_t k){ if(!_safe(A,push())){ return{nullptr,nullptr}; }else if(_safe(A->children[L],size)>=k){ auto[split_L,split_R] =split(A->cut(L),k); return{split_L,A->set(L,split_R)}; }else{ k-=_safe(A->children[L],size)+1; auto[split_L,split_R] =split(A->cut(R),k); return{A->set(R,split_L),split_R}; } } static void exec_on_segment(treap&A,size_t l,size_t r,auto func){ auto[LM,R] =split(A,r); auto[L,M] =split(LM,l); func(M); A=merge(L,merge(M,R)); } static void insert(treap&A,size_t pos,treap t){ auto[L,R] =split(A,pos); A=merge(L,merge(t,R)); } static void erase(treap&A,size_t pos){ auto[L,MR] =split(A,pos); auto[M,R] =split(MR,1); delete M; A=merge(L,R); } static void exec_on_each(treap&A,auto func){ if(A){ exec_on_each(A->children[L],func); func(A); exec_on_each(A->children[R],func); } } treap pull_all(){ _safe(children[L],pull_all()); _safe(children[R],pull_all()); return pull(); } treap push_all(){ push(); _safe(children[L],push_all()); _safe(children[R],push_all()); return this; } static treap build(auto const&nodes){ big_vector<treap>st; for(auto cur:nodes){ while(st.size()>=2&&st[st.size()-2]->prior>cur->prior){ st.pop_back(); } if(!st.empty()&&st.back()->prior>cur->prior){ cur->set(L,st.back()); st.pop_back(); } if(!st.empty()&&st.back()->prior<cur->prior){ st.back()->set(R,cur); } st.push_back(cur); } return st.empty()?nullptr:st[0]->pull_all(); } }; struct null_meta{ void pull(auto const,auto const){} void push(auto&,auto&){} }; }