aboutsummaryrefslogblamecommitdiffstats
path: root/meowpp/dsa/SegmentTree.hpp
blob: 24efcdd0ea8b94c4277af57ad7ad1026679d44f7 (plain) (tree)











































































































































































                                                                              
#ifndef   SegmentTree_H__
#define   SegmentTree_H__

namespace meow{
  template<class Value>
  inline SegmentTree<Value>::Node::Node(){ }

  template<class Value>
  inline size_t
  SegmentTree<Value>::leftChild(size_t __parent) const {
    return __parent * 2 + 1;
  }
  template<class Value>
  inline size_t
  SegmentTree<Value>::rightChild(size_t __parent) const {
    return __parent * 2 + 2;
  }

  template<class Value>
  inline void
  SegmentTree<Value>::downUpdate(size_t __L, size_t __R, size_t __index){
    size_t mid = (__L + __R) / 2;
    Value& val = _nodes[__index]._value;
    Value& off = _nodes[__index]._offset;
    if(_nodes[__index]._sameFlag){
      if(__L < __R){
        override(__L    , mid, __L    , mid,  leftChild(__index), val);
        override(mid + 1, __R, mid + 1, __R, rightChild(__index), val);
      }
      _nodes[__index]._sameFlag = false;
      _nodes[__index]._offset = 0;
    }else if(!(_nodes[__index]._offset == Value(0))){
      if(__L < __R){
        offset(__L    , mid, __L    , mid,  leftChild(__index), off);
        offset(mid + 1, __R, mid + 1, __R, rightChild(__index), off);
      }
      _nodes[__index]._offset = 0;
    }
  }
  template<class Value>
  inline void
  SegmentTree<Value>::override(size_t __l, size_t __r,
                               size_t __L, size_t __R,
                               size_t __index, Value const& __value){
    if(__l == __L && __r == __R){
      _nodes[__index]._value    = __value * (__R - __L + 1);
      _nodes[__index]._offset   = 0;
      _nodes[__index]._sameFlag = true;
      return ;
    }
    downUpdate(__L, __R, __index);
    size_t mid = (__L + __R) / 2;
    if(__r <= mid){
      override(__l, __r, __L    , mid,  leftChild(__index), __value);
    }else if(mid + 1 <= __l){
      override(__l, __r, mid + 1, __R, rightChild(__index), __value);
    }else{
      override(__l    , mid, __L    , mid,  leftChild(__index), __value);
      override(mid + 1, __r, mid + 1, __R, rightChild(__index), __value);
    }
    _nodes[__index]._value = (  _nodes[ leftChild(__index)]._value
                              | _nodes[rightChild(__index)]._value);
  }
  template<class Value>
  inline void
  SegmentTree<Value>::offset(size_t __l, size_t __r,
                             size_t __L, size_t __R,
                             size_t __index, Value const& __delta){
    if(__l == __L && __r == __R){
      _nodes[__index]._value = _nodes[__index]._value + __delta*(__R-__L+1);
      if(!_nodes[__index]._sameFlag){
        _nodes[__index]._offset = _nodes[__index]._offset + __delta;
      }
      return ;
    }
    downUpdate(__L, __R, __index);
    size_t mid = (__L + __R) / 2;
    if(__r <= mid){
      offset(__l, __r, __L    , mid,  leftChild(__index), __delta);
    }else if(mid + 1 <= __l){
      offset(__l, __r, mid + 1, __R, rightChild(__index), __delta);
    }else{
      offset(__l    , mid, __L    , mid,  leftChild(__index), __delta);
      offset(mid + 1, __r, mid + 1, __R, rightChild(__index), __delta);
    }
    _nodes[__index]._value = (  _nodes[ leftChild(__index)]._value
                              | _nodes[rightChild(__index)]._value);
  }
  template<class Value>
  inline Value
  SegmentTree<Value>::query(size_t __l, size_t __r,
                            size_t __L, size_t __R,
                            size_t __index){
    if((__l == __L && __r == __R) || _nodes[__index]._sameFlag){
      return _nodes[__index]._value;
    }
    size_t mid = (__L + __R) / 2;
    Value& off = _nodes[__index]._offset;
    if(__r <= mid){
      return query(__l, __r, __L    , mid,  leftChild(__index)) + off;
    }else if(mid + 1 <= __l){
      return query(__l, __r, mid + 1, __R, rightChild(__index)) + off;
    }else{
      return (  query(__l    , mid, __L    , mid,  leftChild(__index))
              | query(mid + 1, __r, mid + 1, __R, rightChild(__index))) + off;
    }
  }
  template<class Value>
  inline bool
  SegmentTree<Value>::rangeCorrect(ssize_t* __first, ssize_t* __last) const{
    if(*__last < *__first){
      return false;
    }
    if(*__last < 0 || _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<class Value>
  inline
  SegmentTree<Value>::SegmentTree(): _size(0), _root(0) {
  }
  template<class Value>
  inline
  SegmentTree<Value>::SegmentTree(size_t __size): _size(0), _root(0){
    reset(__size);
  }
  template<class Value>
  inline
  SegmentTree<Value>::SegmentTree(SegmentTree const& __tree2):
  _size(__tree2._size), _nodes(__tree2._nodes), _root(0){ }
  //
  template<class Value>
  inline void
  SegmentTree<Value>::reset(size_t __size){
    _size = __size;
    _nodes.resize(__size * 4);
    _nodes[_root]._sameFlag = true;
    _nodes[_root]._value = Value(0);
  }
  template<class Value>
  inline Value
  SegmentTree<Value>::query(ssize_t __first, ssize_t __last) const{
    if(rangeCorrect(&__first, &__last) == false){
      return Value();
    }
    return ((SegmentTree*)this)->query(__first, __last, 0, _size - 1, _root);
  }
  template<class Value>
  inline void
  SegmentTree<Value>::override(ssize_t __first, ssize_t __last,
                               Value const& __value){
    if(rangeCorrect(&__first, &__last) == false){
      return ;
    }
    override(__first, __last, 0, _size - 1, _root, __value);
  }
  template<class Value>
  inline void
  SegmentTree<Value>::offset(ssize_t __first, ssize_t __last,
                             Value const& __delta){
    if(rangeCorrect(&__first, &__last) == false){
      return ;
    }
    offset(__first, __last, 0, _size - 1, _root, __delta);
  }
}

#endif