13template<
class D,
size_t N = 16>
class Sets {
28 constexpr Node(Node* parent, D* def,
u32 id) noexcept
31 , size(parent->size + 1)
32 , min(parent->def ? parent->min : def->tid())
37 constexpr bool lt(D* d)
const noexcept {
return this->is_root() || this->def->tid() < d->tid(); }
38 constexpr bool eq(D* d)
const noexcept {
return this->def == d; }
40 void dot(std::ostream& os) {
41 using namespace std::string_literals;
43 auto node2str = [](
const Node* n) {
44 return "n_"s + (n->def ? std::to_string(n->def->tid()) :
"root"s) +
"_"s + std::to_string(n->id);
47 println(os,
"{} [tooltip=\"gid: {}, min: {}\"];", node2str(
this), def ? def->gid() : 0, min);
49 for (
const auto& [def, child] : children)
println(os,
"{} -> {}", node2str(
this), node2str(child.get()));
50 for (
const auto& [_, child] : children) child->dot(os);
54 if (
auto par =
LCT::path_parent())
println(os,
"{} -> {} [constraint=false,color=\"#0000ff\",style=dashed];", node2str(
this), node2str(par));
55 if (
auto top = aux.
top )
println(os,
"{} -> {} [constraint=false,color=\"#ff0000\"];", node2str(
this), node2str(
top));
56 if (
auto bot = aux.
bot )
println(os,
"{} -> {} [constraint=false,color=\"#00ff00\"];", node2str(
this), node2str(
bot));
63 constexpr bool is_root()
const noexcept {
return def == 0; }
65 [[nodiscard]]
bool contains(D* d)
noexcept {
68 if (tid == this->min || tid == this->def->tid())
return true;
69 if (tid < this->min || tid > this->def->tid())
return false;
87 constexpr Data()
noexcept =
default;
88 constexpr Data(
size_t size) noexcept
95 constexpr bool operator()(
const Data* d1,
const Data* d2)
const noexcept {
96 bool res = d1->size == d2->size;
97 for (
size_t i = 0, e = d1->size; res && i != e; ++i) res &= d1->elems[i] == d2->elems[i];
104 constexpr D** begin() noexcept {
return elems; }
105 constexpr D** end() noexcept {
return elems + size; }
106 constexpr D*
const* begin() const noexcept {
return elems; }
107 constexpr D*
const* end() const noexcept {
return elems + size; }
110 template<
class H>
friend constexpr H AbslHashValue(H h,
const Data* d)
noexcept {
111 if (!d)
return H::combine(std::move(h), 0);
112 return H::combine_contiguous(std::move(h),
d->elems,
d->size);
119 enum class Tag : uintptr_t { Null, Uniq, Data, Node };
121 constexpr Set(
const Data* data) noexcept
122 : ptr_(uintptr_t(data) | uintptr_t(Tag::Data)) {}
123 constexpr Set(Node* node) noexcept
124 : ptr_(uintptr_t(node) | uintptr_t(Tag::Node)) {}
131 , ptr_(std::bit_cast<uintptr_t>(d)) {}
132 constexpr iterator(D*
const* elems) noexcept
134 , ptr_(std::bit_cast<uintptr_t>(elems)) {}
135 constexpr iterator(Node* node) noexcept
137 , ptr_(std::bit_cast<uintptr_t>(node)) {}
157 constexpr iterator& operator++() noexcept {
160 case Tag::Uniq:
return clear();
161 case Tag::Data:
return ptr_ = std::bit_cast<uintptr_t>(std::bit_cast<D* const*>(ptr_) + 1), *
this;
163 auto node = std::bit_cast<Node*>(ptr_);
168 ptr_ = std::bit_cast<uintptr_t>(node);
171 default: fe::unreachable();
186 constexpr bool operator==(iterator other)
const noexcept {
return this->tag_ == other.tag_ && this->ptr_ == other.ptr_; }
187 constexpr bool operator!=(iterator other)
const noexcept {
return this->tag_ != other.tag_ || this->ptr_ != other.ptr_; }
195 case Tag::Uniq:
return *std::bit_cast<D* const*>(&ptr_);
196 case Tag::Data:
return *std::bit_cast<D* const*>(ptr_);
197 case Tag::Node:
return std::bit_cast<Node*>(ptr_)->def;
198 default: fe::unreachable();
205 iterator&
clear() {
return tag_ = Tag::Null, ptr_ = 0, *
this; }
216 constexpr Set(
const Set&)
noexcept =
default;
217 constexpr Set(Set&&) noexcept = default;
218 constexpr Set() noexcept = default;
219 constexpr Set(D* d) noexcept
220 : ptr_(uintptr_t(d) | uintptr_t(Tag::Uniq)) {}
222 constexpr Set&
operator=(
const Set&)
noexcept =
default;
227 constexpr size_t size() const noexcept {
228 if (isa_uniq())
return 1;
229 if (
auto d = isa_data())
return d->size;
230 if (
auto n = isa_node())
return n->size;
235 constexpr bool empty() const noexcept {
236 assert(tag() != Tag::Node || !ptr<Node>()->is_root());
240 constexpr explicit operator bool() const noexcept {
return ptr_ != 0; }
248 if (
auto u = isa_uniq())
return d == u;
250 if (
auto data = isa_data()) {
252 if (d == e)
return true;
256 if (
auto n = isa_node())
return n->contains(d);
263 if (this->
empty() || other.empty())
return false;
265 auto u1 = this->isa_uniq();
266 auto u2 = other.isa_uniq();
267 if (
u1 && u2)
return u1 == u2;
268 if (
u1)
return other.contains(
u1);
271 auto d1 = this->isa_data();
272 auto d2 = other.isa_data();
274 if (d1 == d2)
return true;
276 for (
auto ai = d1->begin(), ae = d1->end(), bi = d2->begin(), be = d2->end(); ai != ae && bi != be;) {
277 if (*ai == *bi)
return true;
279 if ((*ai)->gid() < (*bi)->gid())
288 auto n1 = this->isa_node();
289 auto n2 = other.isa_node();
291 if (n1->min > n2->def->tid() || n1->def->tid() < n2->min)
return false;
292 if (n1->def == n2->def)
return true;
293 if (!n1->lca(n2)->is_root())
return true;
295 while (!n1->is_root() && !n2->is_root()) {
296 if (n1->def->tid() > n2->def->tid()) {
297 if (n1 = n1->find(n2->def); n2->def == n1->def)
return true;
300 if (n2 = n2->find(n1->def); n1->def == n2->def)
return true;
308 auto n = n1 ? n1 : n2;
309 for (
auto e : *(d1 ? d1 : d2))
310 if (n->contains(e))
return true;
319 if (
auto u = isa_uniq())
return {u};
320 if (
auto d = isa_data())
return {d->begin()};
321 if (
auto n = isa_node(); n && !n->is_root())
return {n};
326 if (
auto data = isa_data())
return iterator(data->end());
333 constexpr bool operator==(Set other)
const noexcept {
return this->ptr_ == other.ptr_; }
334 constexpr bool operator!=(Set other)
const noexcept {
return this->ptr_ != other.ptr_; }
339 std::ostream&
stream(std::ostream& os)
const {
342 for (
auto d : *
this) {
343 os << sep << d->gid() <<
'/' << d->tid();
353 constexpr Tag tag() const noexcept {
return Tag(ptr_ & uintptr_t(0b11)); }
354 template<
class T>
constexpr T* ptr() const noexcept {
355 return std::bit_cast<T*>(ptr_ & (uintptr_t(-2) << uintptr_t(2)));
358 constexpr D* isa_uniq() const noexcept {
return tag() == Tag::Uniq ? ptr<D >() : nullptr; }
359 constexpr Data* isa_data() const noexcept {
return tag() == Tag::Data ? ptr<Data>() : nullptr; }
360 constexpr Node* isa_node() const noexcept {
return tag() == Tag::Node ? ptr<Node>() : nullptr; }
369 static_assert(std::forward_iterator<typename Set::iterator>);
370 static_assert(std::ranges::range<Set>);
377 : root_(make_node()) {}
393 std::sort(vb, ve, [](D* d1, D* d2) {
return d1->gid() < d2->gid(); });
394 auto vu = std::unique(vb, ve);
395 auto size = std::distance(vb, vu);
397 if (
size == 0)
return {};
398 if (
size == 1)
return {*vb};
400 if (
size_t(
size) <= N) {
401 auto [data, state] = allocate(
size);
402 std::copy(vb, vu, data->begin());
403 return unify(data, state);
407 std::sort(vb, vu, [](D* d1, D* d2) {
return d1->tid() != 0 && (d2->tid() == 0 || d1->tid() < d2->tid()); });
410 for (
auto i = vb; i != vu; ++i) res =
insert(res, *i);
416 if (
auto u = s.isa_uniq()) {
417 if (d == u)
return {d};
419 auto [data, state] = allocate(2);
420 if (d->gid() < u->gid())
421 data->elems[0] = d, data->elems[1] = u;
423 data->elems[0] = u, data->elems[1] = d;
424 return unify(data, state);
427 if (
auto src = s.isa_data()) {
428 auto size = src->size;
430 auto [dst, state] = allocate(
size + 1);
434 for (
auto si = src->begin(), di = dst->begin(), se = src->end(); si != se || !ins; ++di) {
435 if (si != se && d == *si) {
436 data_arena_.deallocate(state);
440 if (!ins && (si == se || d->gid() < (*si)->gid()))
446 return unify(dst, state);
448 auto [dst, state] = allocate(
size + 1);
451 auto di = dst->begin();
452 for (
auto si = src->begin(), se = src->end(); si != se; ++si, ++di) {
454 data_arena_.deallocate(state);
463 std::sort(dst->begin(), di,
464 [](D* d1, D* d2) { return d1->tid() != 0 && (d2->tid() == 0 || d1->tid() < d2->tid()); });
467 for (
auto i = dst->begin(), e = dst->end(); i != e; ++i) res =
insert(res, *i);
472 if (
auto n = s.isa_node()) {
473 if (n->contains(d))
return n;
481 [[nodiscard]] Set
merge(Set s1, Set s2) {
482 if (s1.empty() || s1 == s2)
return s2;
483 if (s2.empty())
return s1;
485 if (
auto u = s1.isa_uniq())
return insert(s2, u);
486 if (
auto u = s2.isa_uniq())
return insert(s1, u);
488 auto d1 = s1.isa_data();
489 auto d2 = s2.isa_data();
492 v.reserve(d1->size + d2->size);
494 for (
auto d : *d1) v.emplace_back(d);
495 for (
auto d : *d2) v.emplace_back(d);
497 return create(std::move(v));
500 auto n1 = s1.isa_node();
501 auto n2 = s2.isa_node();
503 if (n1->is_descendant_of(n2))
return n1;
504 if (n2->is_descendant_of(n1))
return n2;
505 return merge(n1, n2);
508 auto n = n1 ? n1 : n2;
509 for (
auto d : *(d1 ? d1 : d2))
510 if (!n->contains(d)) n =
insert(n, d);
515 [[nodiscard]] Set
erase(Set s, D* d) {
516 if (
auto u = s.isa_uniq())
return d == u ? Set() : s;
518 if (
auto data = s.isa_data()) {
519 size_t i = 0,
size = data->size;
520 for (; i !=
size; ++i)
521 if (data->elems[i] == d)
break;
523 if (i ==
size--)
return s;
524 if (
size == 0)
return {};
525 if (
size == 1)
return {i == 0 ? data->elems[1] : data->elems[0]};
528 auto [new_data, state] = allocate(
size);
529 auto db = data->begin();
530 std::copy(db + i + 1, data->end(), std::copy(db, db + i, new_data->elems));
532 return unify(new_data, state);
535 if (
auto n = s.isa_node()) {
536 if (d->tid() == 0 || d->tid() < n->min)
return n;
537 if (!n->contains(d))
return n;
539 auto res =
erase(n, d);
540 if (res->size > N)
return res;
543 v.reserve(res->size);
544 for (
auto i = res; !i->is_root(); i = i->parent) v.emplace_back(i->def);
545 return create(std::move(v));
554 auto of = std::ofstream(
"trie.dot");
558 void dot(std::ostream& os)
const {
559 os <<
"digraph {{" << std::endl;
560 os <<
"ordering=out;" << std::endl;
561 os <<
"node [shape=box,style=filled];" << std::endl;
563 os <<
"}}" << std::endl;
569 swap(s1.data_arena_, s2.data_arena_);
570 swap(s1.node_arena_, s2.node_arena_);
571 swap(s1.pool_, s2.pool_);
572 swap(s1.root_, s2.root_);
573 swap(s1.tid_counter_, s2.tid_counter_);
574 swap(s1.id_counter_ , s2.id_counter_ );
579 D* set_tid(D* def)
noexcept {
580 assert(def->tid() == 0);
581 def->tid_ = tid_counter_++;
587 inline static constexpr size_t SizeOf =
sizeof(std::conditional_t<std::is_pointer_v<T>, uintptr_t, T>);
590 std::pair<Data*, fe::Arena::State> allocate(
size_t size) {
591 auto bytes =
sizeof(Data) + size * SizeOf<D>;
592 auto state = data_arena_.state();
593 auto buff = data_arena_.allocate(bytes,
alignof(Data));
594 auto data =
new (buff) Data(size);
595 return {data, state};
598 Set unify(Data* data, fe::Arena::State state,
size_t excess = 0) {
599 assert(data->size != 0);
600 auto [i, ins] = pool_.emplace(data);
602 data_arena_.deallocate(excess * SizeOf<D>);
606 data_arena_.deallocate(state);
611 constexpr Node* root() const noexcept {
return root_.get(); }
612 fe::Arena::Ptr<Node> make_node() {
return node_arena_.mk<Node>(id_counter_++); }
613 fe::Arena::Ptr<Node> make_node(Node* parent, D* def) {
return node_arena_.mk<Node>(parent, def, id_counter_++); }
615 [[nodiscard]] Node* mount(Node* parent, D* def) {
616 assert(def->tid() != 0);
617 auto [i, ins] = parent->children.emplace(def,
nullptr);
618 if (ins) i->second = make_node(parent, def);
619 return i->second.get();
622 [[nodiscard]]
constexpr Node*
insert(Node* n, D* d)
noexcept {
623 if (
d->tid() == 0)
return mount(n, set_tid(d));
624 if (n->def == d)
return n;
625 if (n->is_root() || n->def->tid() <
d->tid())
return mount(n, d);
626 return mount(
insert(n->parent, d), n->def);
629 [[nodiscard]]
constexpr Node*
merge(Node* n, Node* m) {
630 if (n == m ||
m->is_root())
return n;
631 if (n->is_root())
return m;
632 auto nn = n->def->tid() <
m->def->tid() ? n : n->parent;
633 auto mm = n->def->tid() >
m->def->tid() ?
m :
m->parent;
634 return mount(
merge(nn, mm), n->def->tid() <
m->def->tid() ?
m->def : n->def);
637 [[nodiscard]] Node*
erase(Node* n, D* d) {
638 if (
d->tid() > n->def->tid())
return n;
639 if (n->def == d)
return n->parent;
640 return mount(
erase(n->parent, d), n->def);
643 fe::Arena node_arena_;
644 fe::Arena data_arena_;
645 absl::flat_hash_set<const Data*, absl::Hash<const Data*>,
typename Data::Equal> pool_;
646 fe::Arena::Ptr<Node> root_;
647 u32 tid_counter_ = 1;
constexpr iterator & operator++() noexcept
constexpr iterator() noexcept=default
constexpr pointer operator->() const noexcept
constexpr bool operator!=(iterator other) const noexcept
constexpr reference operator*() const noexcept
std::forward_iterator_tag iterator_category
std::ptrdiff_t difference_type
constexpr iterator operator++(int) noexcept
constexpr bool operator==(iterator other) const noexcept
bool has_intersection(Set other) const noexcept
Is ?.
constexpr bool empty() const noexcept
Is empty?
constexpr bool operator==(Set other) const noexcept
constexpr Set() noexcept=default
Null set.
constexpr Set(const Set &) noexcept=default
constexpr iterator begin() const noexcept
constexpr size_t size() const noexcept
friend std::ostream & operator<<(std::ostream &os, Set set)
std::ostream & stream(std::ostream &os) const
bool contains(D *d) const noexcept
Is ?.
constexpr Set & operator=(const Set &) noexcept=default
constexpr Set(Set &&) noexcept=default
constexpr bool operator!=(Set other) const noexcept
constexpr iterator end() const noexcept
friend void swap(Sets &s1, Sets &s2) noexcept
void dot(std::ostream &os) const
Set merge(Set s1, Set s2)
Yields .
constexpr Sets(const Sets &) noexcept=delete
Sets & operator=(const Sets &)=delete
constexpr Sets() noexcept
constexpr Sets(Sets &&other) noexcept
Set erase(Set s, D *d)
Yields .
Set insert(Set s, D *d)
Yields .
Set create(Vector< D * > v)
Create a Set wih all elements in v.
This is a thin wrapper for absl::InlinedVector<T, N, A> which is a drop-in replacement for std::vecto...
This is an intrusive Link-Cut-Tree.
constexpr void link(Node *child) noexcept
Registers the edge this -> child in the aux tree.
bool contains(const D *&k) noexcept
constexpr Node * path_parent() noexcept
constexpr Node * find(const D *&k) noexcept
constexpr Node() noexcept=default
absl::flat_hash_map< K, V, GIDHash< K >, GIDEq< K > > GIDMap
std::ostream & println(std::ostream &os, const char *fmt, Args &&... args)
As above but end with std::endl.
Vector(I, I, A=A()) -> Vector< typename std::iterator_traits< I >::value_type, Default_Inlined_Size< typename std::iterator_traits< I >::value_type >, A >
constexpr bool operator()(const Data *d1, const Data *d2) const noexcept