Segment Tree
Info
Monoidの区間fold、一点更新が\(O(\log{n})\)でできるデータ構造
Complexity
構築 - \(O(n)\)
1点更新 - \(O(\log{n})\)
1点取得 - \(O(1)\)
区間fold - \(O(\log{n})\)
Interface
SegmentTree<M>(int n) モノイド\(M\)、大きさ\(n\)で初期化する
[int i] \(i\)番目の要素への参照を返す
build() セグ木を構築する
update(int i, M a) \(i\)番目の要素を\(a\)に変更する
fold(int l, int r) 区間\([l,r)\)をfoldした値を返す
Interface(Monoid)
I() 単位元を返す
f(M lhs, M rhs) モノイド間の演算\(f:(M,M)\rightarrow M\)
Code
using lnt=long long;
/* <SegmentTree> */
template<typename M>
struct SegmentTree
{
const int n;
std::vector<M> data;
SegmentTree(int n) : n(n),data(n<<1,M::I()) {}
M& operator[](int i) { return data[i+n]; } // get / pair with build
void update(int i, const M& a) { data[i+n]=a; for(i+=n;i>1;i>>=1) data[i>>1]=M::f(data[i],data[i^1]); }
void build() { for(int i=n-1;i>0;i--) data[i]=M::f(data[i<<1],data[i<<1|1]); }
M fold(int l, int r) const {
M L=M::I(),R=M::I();
for(l+=n,r+=n;l<r;l>>=1,r>>=1) {
if(l&1) L=M::f(data[l++],L);
if(r&1) R=M::f(R,data[--r]);
}
return M::f(L,R);
}
};
/* <SegmentTree> */
/* <SegmentTree::Template> */
template<typename T=lnt>
struct Template
{
T v; bool alive;
static Template I() { return Template(); }
Template() : alive(false) {}
Template(T v) : v(v),alive(true) {}
static Template f(const Template& lhs, const Template& rhs) {
if(lhs.alive&&rhs.alive) return Template(lhs.v+rhs.v);
return (lhs.alive)?lhs:rhs;
}
operator T() const { return v; }
};
/* <SegmentTree::Template> */
/* <SegmentTree::RangeSum> */
template<typename T=lnt>
struct RangeSum
{
T v;
static RangeSum I() { return RangeSum(0); }
RangeSum(T v) : v(v) {}
static RangeSum f(const RangeSum& lhs, const RangeSum& rhs) {
return lhs+rhs;
}
operator T() const { return v; }
};
/* <SegmentTree::RangeSum> */
/* <SegmentTree::RangeMin> */
template<typename T=lnt>
struct RangeMin
{
T v;
static RangeMin I() { return RangeMin(std::numeric_limits<T>::max()); }
RangeMin(T v) : v(v) {}
static RangeMin f(const RangeMin& lhs, const RangeMin& rhs) {
return std::min(lhs,rhs);
}
operator T() const { return v; }
};
/* <SegmentTree::RangeMin> */
/* <SegmentTree::RangeMax> */
template<typename T=lnt>
struct RangeMax
{
T v;
static RangeMax I() { return RangeMax(std::numeric_limits<T>::min()); }
RangeMax(T v) : v(v) {}
static RangeMax f(const RangeMax& lhs, const RangeMax& rhs) {
return std::max(lhs,rhs);
}
operator T() const { return v; }
};
/* <SegmentTree::RangeMax> */
/* <SegmentTree::RangeMinIndex> */
template<typename T=lnt>
struct RangeMinIndex
{
T v; int i;
static RangeMinIndex I() { return RangeMinIndex(std::numeric_limits<T>::max()); }
RangeMinIndex(T v, int i=-1) : v(v),i(i) {}
static RangeMinIndex f(const RangeMinIndex& lhs, const RangeMinIndex& rhs) {
if(lhs.v<rhs.v) return lhs; else return rhs;
}
operator T() const { return v; }
};
/* <SegmentTree::RangeMinIndex> */Examples
using M=RangeMax<int>;
SegmentTree<M> seg(10);
for(int i=0;i<10;i++) seg[i]=i;
seg.build();
std::cout << seg.fold(2,5) << '\n'; // 4
seg.update(2,seg[2]*100);
std::cout << seg.fold(2,5) << '\n'; // 200