#include "SegmentTree.h" #include "../math/utility.h" #include #include #include namespace meow{ template inline void SegmentTree::update(size_t __i, size_t __size, Value const& __value, bool __over){ if(__over){ _nodes[__i]._value = __value * __size; _nodes[__i]._offset = __value; _nodes[__i]._sameFlag = true; }else{ _nodes[__i]._value = _nodes[__i]._value + __value * __size; _nodes[__i]._offset = _nodes[__i]._offset + __value; } } template inline void SegmentTree::update(size_t __l, size_t __r, size_t __L, size_t __R, size_t __i, Value const& __value, bool __over){ if(__l == __L && __r == __R){ update(__i, __R - __L + 1, __value, __over); return ; } size_t mid = (__L + __R) / 2; if(__L < __R){ update(__i*2+1, mid-__L+1, _nodes[__i]._offset, _nodes[__i]._sameFlag); update(__i*2+2, __R - mid, _nodes[__i]._offset, _nodes[__i]._sameFlag); _nodes[__i]._offset = Value(0); _nodes[__i]._sameFlag = false; } if (__r <= mid) update(__l,__r, __L ,mid, __i*2+1, __value, __over); else if(mid+1 <= __l) update(__l,__r, mid+1,__R, __i*2+2, __value, __over); else{ update(__l,mid , __L,mid , __i*2+1, __value, __over); update( mid+1, __r, mid+1, __R, __i*2+2, __value, __over); } _nodes[__i]._value = ( (_nodes[__i * 2 + 1]._value | _nodes[__i * 2 + 2]._value) + _nodes[__i]._offset ); } template inline Value SegmentTree::query(size_t __l, size_t __r, size_t __L, size_t __R, size_t __i){ if(__l == __L && __r == __R) return _nodes[__i]._value; Value off = _nodes[__i]._offset * (__r - __l + 1); if(_nodes[__i]._sameFlag) return off; size_t mid = (__L + __R) / 2; if (__r <= mid) return query(__l,__r, __L , mid, __i*2+1) + off; else if(mid+1 <= __l) return query(__l,__r, mid+1, __R, __i*2+2) + off; else{ return ( query(__l, mid , __L, mid, __i*2+1) | query( mid+1, __r, mid+1, __R, __i*2+2) ) + off; } } // template inline bool SegmentTree::rangeCorrect(ssize_t* __first, ssize_t* __last) const{ if(*__last<*__first || *__last<0 || (ssize_t)_size-1<*__first) return false; *__first = inRange((ssize_t)0, (ssize_t)_size - 1, *__first); *__last = inRange((ssize_t)0, (ssize_t)_size - 1, *__last ); return true; } // template inline SegmentTree::SegmentTree(){ reset(1); } template inline SegmentTree::SegmentTree(size_t __size){ reset(__size); } template inline SegmentTree::SegmentTree(SegmentTree const& __tree2): _size(__tree2._size), _nodes(__tree2._nodes){ } // template inline void SegmentTree::reset(size_t __size){ _size = std::max(__size, (size_t)1); _nodes.resize(__size * 4); _nodes[0]._sameFlag = true; _nodes[0]._value = Value(0); _nodes[0]._offset = Value(0); } template inline Value SegmentTree::query(ssize_t __first, ssize_t __last) const{ if(rangeCorrect(&__first, &__last) == false) return Value(); return ((SegmentTree*)this)->query(__first, __last, 0, _size - 1, 0); } template inline void SegmentTree::override(ssize_t __first, ssize_t __last, Value const& __value){ if(rangeCorrect(&__first, &__last) == false) return ; update(__first, __last, 0, _size - 1, 0, __value, true); } template inline void SegmentTree::offset(ssize_t __first, ssize_t __last, Value const& __delta){ if(rangeCorrect(&__first, &__last) == false) return ; update(__first, __last, 0, _size - 1, 0, __delta, false); } }