Chtholly Tree (ODT)
/**
* author: Gyan083 inaku.gs
*
* 2021.10.24
*
*
*/
/** @file include/Chtholly.cpp
* This is a Non-standard C++ header.
*/
#ifndef _CHTHOLLY
#define _CHTHOLLY 1
#include <set>
#include <functional>
namespace __ODT_
{
template<typename Tp, typename comp = std::equal_to<Tp> >
/**
* comp(a,b) to decide if they can be merged
* std::equal_to<_Tp> comes from <functional> (stl_function.h)
*
*/
class Chtholly {
public:
class iterator;//declare iterator
private:
struct node {//nodes in the set
const int l;
mutable int r;
mutable Tp val;
node() = delete;//for safety
node(int L) : l(L) { }//for convenience
node(int L, int R, const Tp& V) : l(L), r(R), val(V) { }
bool operator < (const node& y) const {//for set's comparison
return l < y.l;
}
};
std::set<node> st;
typedef typename std::set<node>::iterator IT;
int _size_n;
iterator _begin_iterator, _end_iterator;
IT split(int pos) {
if (pos<1) return st.begin();//A programmer get into a bar...
IT it(std::prev(st.upper_bound(pos)));
if (it->r < pos) return st.end();//Another programmer get into the bar...
if (it->l == pos) return it;
int tmpr = it->r;
it->r = pos - 1;
return st.insert(node(pos, tmpr, it->val)).first;
}
IT merge(IT i) {
IT l(i), r(i);//caution: [l,r)
while (l != st.begin()
&& comp()(prev(l)->val, i->val)
) --l;
while (r != st.end()
&& comp()(r->val, i->val)
) ++r;
int tl(l->l), tr(prev(r)->r);
Tp tv(i->val);
if (tl>tr) return i;//
st.erase(l, r);
return st.insert(node(tl, tr, tv)).first;
}
void merge(IT l, IT r) {//[l,r]
int ed(r->r);
while (l->r < ed) l=next(merge(l));
}
void merge()
{ merge(st.begin(), --st.end()); }
public:
Chtholly()//an empty sequence
: st(), _size_n(0),
_begin_iterator(1, st.begin()), _end_iterator(_size_n+1, st.end())
{ }
Chtholly(int n, const Tp& val)
: st(), _size_n(n)
{
st.insert(node(1, n, val));
_begin_iterator = iterator(1, st.begin());
_end_iterator = iterator(_size_n+1, st.end());
}
template<typename FI>
Chtholly(FI first, FI end)//copy value from [first,end)
: st(), _size_n(0)
{
if (first == end) return;
Tp val(*first++);
int l(1), r(1);
while (first != end) {
if ( !comp()(*first, val) ) {
_size_n += r-l+1;
st.insert(node(l, r, val));
val = *first;
l = r + 1;
}
++first, ++r;
}
_size_n += r-l+1;
st.insert(node(l, r, val));
_begin_iterator = iterator(1, st.begin());
_end_iterator = iterator(_size_n+1, st.end());
}
void clear()
{ st.clear(); }
void rebuild()
{ *this = Chtholly(); }
void rebuild(int n, const Tp& val)
{ *this = Chtholly(n, val); }
template<typename FI>
void rebuild(FI first, FI end)
{ *this = Chtholly(first, end); }
void assign(int l, int r, const Tp& val) {//force to remake [l,r] val
if (l>r) return;
IT itr(split(r+1)), itl(split(l));
st.erase(itl, itr);
IT i = st.insert(node(l, r, val)).first;
merge(i);
}
template<typename Rtn, typename... ArgList>
void operate(int l , int r, Rtn (*func)(iterator, ArgList...), ArgList... arg) {
if (l>r) return;//The third programmer ask for a bunch of noodles...
if (l<1) l = 1;
if (r>size()) r = size();
IT itr(split(r+1)), itl(split(l));
for (IT it(itl); it!=itr; ++it) {
func(iterator(it->l, it), arg...);
}
merge(itl, itr);
}
template<typename FI>//copy [l,r] to 'destin'
void copy_to(FI destin, int l, int r) const {
if (l>r) return;
IT it(--st.upper_bound(l));
while (it != st.end()) {
int lim(std::min(it->r, r));
while (l <= lim) *destin++=it->val, ++l;
if (l>r) return;
++it;
}
}
const Tp operator [] (const int pos) const//you shound not change its value
{ return std::prev(st.upper_bound(pos))->val; }
//O(log n)
int size() const//length of the real array
{ return _size_n; }
iterator begin() const
{ return _begin_iterator; }
iterator end() const
{ return _end_iterator; }
int bsize() const
{ return st.size(); }
class iterator {
private:
int pos;//iterator in the real array
IT it;//iterator in set
public:
iterator() = default;//for safety
iterator(int ind, const IT& i)
: pos(ind), it(i) { }
iterator operator ++ () {
if (++pos > it->r) ++it;
return *this;
}
iterator operator ++ (int) {
iterator tmp = *this;
return ++*this, tmp;
}
iterator operator -- () {
if (--pos < it->l) --it;
return *this;
}
iterator operator -- (int) {
iterator tmp = *this;
return --*this, tmp;
}
bool operator == (const iterator& _x) const { return pos == _x.pos; }
bool operator != (const iterator& _x) const { return pos != _x.pos; }
bool operator < (const iterator& _x) const { return pos < _x.pos; }
bool operator > (const iterator& _x) const { return pos > _x.pos; }
bool operator <= (const iterator& _x) const { return pos <= _x.pos; }
bool operator >= (const iterator& _x) const { return pos >= _x.pos; }
Tp& operator * () { return it->val; }
const Tp val() { return **this; }
const int left() const { return it->l; }
const int right() const { return it->r; }
iterator prev() const { return iterator(it->l - 1, std::prev(it)); }
iterator next() const { return iterator(it->r + 1, std::next(it)); }
};//class iterator
};//class Chtholly
}//namespace __ODT_
#endif // _CHTHOLLY
压缩版(仅有一行便于复制):
template<typename Tp,typename comp=std::equal_to<Tp>>class Chtholly{public:class iterator;private:struct node{const int l;mutable int r;mutable Tp val;node()=delete;node(int L):l(L){}node(int L,int R,const Tp&V):l(L),r(R),val(V){}bool operator<(const node&y)const{return l<y.l;}};std::set<node>st;typedef typename std::set<node>::iterator IT;int _size_n;iterator _begin_iterator,_end_iterator;IT split(int pos){if(pos<1)return st.begin();IT it(std::prev(st.upper_bound(pos)));if(it->r<pos)return st.end();if(it->l==pos)return it;int tmpr=it->r;it->r=pos-1;return st.insert(node(pos,tmpr,it->val)).first;}IT merge(IT i){IT l(i),r(i);while(l!=st.begin()&&comp()(prev(l)->val,i->val))--l;while(r!=st.end()&&comp()(r->val,i->val))++r;int tl(l->l),tr(prev(r)->r);Tp tv(i->val);if(tl>tr)return i;st.erase(l,r);return st.insert(node(tl,tr,tv)).first;}void merge(IT l,IT r){int ed(r->r);while(l->r<ed)l=next(merge(l));}void merge(){merge(st.begin(),--st.end());}public:Chtholly():st(),_size_n(0),_begin_iterator(1,st.begin()),_end_iterator(_size_n+1,st.end()){}Chtholly(int n,const Tp&val):st(),_size_n(n){st.insert(node(1,n,val));_begin_iterator=iterator(1,st.begin());_end_iterator=iterator(_size_n+1,st.end());}template<typename FI>Chtholly(FI first,FI end):st(),_size_n(0){if(first==end)return;Tp val(*first++);int l(1),r(1);while(first!=end){if(!comp()(*first,val)){_size_n+=r-l+1;st.insert(node(l,r,val));val=*first;l=r+1;}++first,++r;}_size_n+=r-l+1;st.insert(node(l,r,val));_begin_iterator=iterator(1,st.begin());_end_iterator=iterator(_size_n+1,st.end());}void clear(){st.clear();}void rebuild(){*this=Chtholly();}void rebuild(int n,const Tp&val){*this=Chtholly(n,val);}template<typename FI>void rebuild(FI first,FI end){*this=Chtholly(first,end);}void assign(int l,int r,const Tp&val){if(l>r)return;IT itr(split(r+1)),itl(split(l));st.erase(itl,itr);IT i=st.insert(node(l,r,val)).first;merge(i);}template<typename Rtn,typename...ArgList>void operate(int l,int r,Rtn(*func)(iterator,ArgList...),ArgList...arg){if(l>r)return;if(l<1)l=1;if(r>size())r=size();IT itr(split(r+1)),itl(split(l));for(IT it(itl);it!=itr;++it){func(iterator(it->l,it),arg...);}merge(itl,itr);}template<typename FI>void copy_to(FI destin,int l,int r)const{if(l>r)return;IT it(--st.upper_bound(l));while(it!=st.end()){int lim(std::min(it->r,r));while(l<=lim)*destin++=it->val,++l;if(l>r)return;++it;}}const Tp operator[](const int pos)const{return std::prev(st.upper_bound(pos))->val;}int size()const{return _size_n;}iterator begin()const{return _begin_iterator;}iterator end()const{return _end_iterator;}int bsize()const{return st.size();}class iterator{private:int pos;IT it;public:iterator()=default;iterator(int ind,const IT&i):pos(ind),it(i){}iterator operator++(){if(++pos>it->r)++it;return*this;}iterator operator++(int){iterator tmp=*this;return++*this,tmp;}iterator operator--(){if(--pos<it->l)--it;return*this;}iterator operator--(int){iterator tmp=*this;return--*this,tmp;}bool operator==(const iterator&_x)const{return pos==_x.pos;}bool operator!=(const iterator&_x)const{return pos!=_x.pos;}bool operator<(const iterator&_x)const{return pos<_x.pos;}bool operator>(const iterator&_x)const{return pos>_x.pos;}bool operator<=(const iterator&_x)const{return pos<=_x.pos;}bool operator>=(const iterator&_x)const{return pos>=_x.pos;}Tp&operator*(){return it->val;}const Tp val(){return**this;}const int left()const{return it->l;}const int right()const{return it->r;}iterator prev()const{return iterator(it->l-1,std::prev(it));}iterator next()const{return iterator(it->r+1,std::next(it));}};};
请及时向我反映 bug ,谢谢。