---
# System prepended metadata

title: segment tree
tags: [codebook]

---

---
tags: codebook
---

# segment tree


## basic

```cpp=
constexpr int maxn=2e5+5;
ll arr[(maxn+1)<<2];
 
#define m ((l+r)>>1)
void build(V<int>& v,int i=1,int l=0,int r=maxn){
    if((int)v.size()<=l) return;
    if(r-l==1){arr[i]=v[l];return;}
    
    build(v,i<<1,l,m),build(v,i<<1|1,m,r);
 
    arr[i]=min(arr[i<<1],arr[i<<1|1]);
}
 
void modify(int k,int u,int i=1,int l=0,int r=maxn){
    if(k<l||r<=k) return;
    if(r-l==1){arr[i]=u;return;}
 
    modify(k,u,i<<1,l,m),modify(k,u,i<<1|1,m,r);
    
    arr[i]=min(arr[i<<1],arr[i<<1|1]);
}
 
ll query(int ql,int qr,int i=1,int l=0,int r=maxn){
    if(qr<=l||r<=ql) return LINF;
    if(ql<=l&&r<=qr) return arr[i];
 
    return min(query(ql,qr,i<<1,l,m),query(ql,qr,i<<1|1,m,r));
}
 
 
static inline void solve(){
    int n,q;cin>>n>>q;
    V<int> v(n);
    for(auto& i:v)
        cin>>i;
    build(v);
    while(q--){
        int op;cin>>op;
        switch(op){
            case 1:{
                int k,u;cin>>k>>u,k--;
                modify(k,u);
            }break;    
            case 2:{
                int a,b;cin>>a>>b,a--;
                cout<<query(a,b)<<endl;
            }break;
        }
    }
}
```

## with lazy propagation

```cpp=
constexpr int maxn=2e5+5;
ll arr[(maxn+1)<<2],set[(maxn+1)<<2],inc[(maxn+1)<<2];
 
#define m ((l+r)>>1)
void push(int i,int l,int r){
    if(r-l==1) return;
    if(set[i]){
        arr[i]=(r-l)*set[i];
        set[i<<1]=set[i<<1|1]=set[i];
        inc[i<<1]=inc[i<<1|1]=0;
        set[i]=0;
    }
    if(inc[i]){
        arr[i]+=(r-l)*inc[i];
        inc[i<<1]+=inc[i];
        inc[i<<1|1]+=inc[i];
        inc[i]=0;
    }
}
void pull(int i,int l,int r){
    if(r-l==1) return;
    arr[i]=0;
    if(set[i<<1])
        arr[i]+=set[i<<1]*(m-l);
    else
        arr[i]+=arr[i<<1];
    arr[i]+=inc[i<<1]*(m-l);
 
    if(set[i<<1|1])
        arr[i]+=set[i<<1|1]*(r-m);
    else
        arr[i]+=arr[i<<1|1];
    arr[i]+=inc[i<<1|1]*(r-m);
}
 
void build(V<int>& v,int i=1,int l=0,int r=maxn){
    if((int)v.size()<=l) return;
    if(r-l==1){arr[i]=v[l];return;}
    
    build(v,i<<1,l,m),build(v,i<<1|1,m,r);
 
    pull(i,l,r);
}
 
void increase(int ql,int qr,int x,int i=1,int l=0,int r=maxn){
    if(qr<=l||r<=ql) return;
    if(ql<=l&&r<=qr){
        inc[i]+=x;
        return;
    }
 
    push(i,l,r);
 
    increase(ql,qr,x,i<<1,l,m),increase(ql,qr,x,i<<1|1,m,r);
 
    pull(i,l,r);
}
 
void modify(int ql,int qr,int x,int i=1,int l=0,int r=maxn){
    if(qr<=l||r<=ql) return;
    if(ql<=l&&r<=qr){
        set[i]=x,inc[i]=0;
        return;
    }
 
    push(i,l,r);
 
    modify(ql,qr,x,i<<1,l,m),modify(ql,qr,x,i<<1|1,m,r);
 
    pull(i,l,r);
}
 
ll query(int ql,int qr,int i=1,int l=0,int r=maxn){
    if(qr<=l||r<=ql) return 0;
    if(ql<=l&&r<=qr){ 
        ll ret=arr[i];
        if(set[i])
            ret=set[i]*(r-l);
        ret+=inc[i]*(r-l);
        return ret;
    }
    push(i,l,r);
 
    return query(ql,qr,i<<1,l,m)+query(ql,qr,i<<1|1,m,r);
}
#undef m
```

## with persistency
```cpp=
constexpr int maxn=2e5+5;
 
 
struct node{
    ll val;
    node *l,*r;
 
    node(ll x=0):val(x){
        l=r=nullptr;
    }
    void pull(){
        val=0;
        for(auto i:{l,r})
            if(i) val+=i->val;
    }
};
 
 
 
#define m ((l+r)>>1)
 
node* build(V<int>& v,int l=0,int r=maxn){
    if((int)v.size()<=l) return nullptr;
    if(r-l==1) return new node(v[l]);
    
    node *ret=new node;
    ret->l=build(v,l,m);
    ret->r=build(v,m,r);
    
    ret->pull();
    return ret;
}
 
node* modify(node* rt,int k,int x,int l=0,int r=maxn){
    if(k<l||r<=k) return rt;
    if(r-l==1) return new node(x);
 
    node* ret=new node;
    ret->l=modify(rt->l,k,x,l,m);
    ret->r=modify(rt->r,k,x,m,r);
 
    ret->pull();
    return ret;
}
 
ll query(node* rt,int ql,int qr,int l=0,int r=maxn){
    if(qr<=l||r<=ql||!rt) return 0;
    if(ql<=l&&r<=qr) return rt->val;
 
    return query(rt->l,ql,qr,l,m)+query(rt->r,ql,qr,m,r);
}
 
#undef m
 
#define endl '\n'
static inline void solve(){
    int n,q;cin>>n>>q;
    V<int> v(n);
    for(auto& i:v)
        cin>>i;
    V<node*> root{build(v)};
    while(q--){
        int op;cin>>op;
        switch(op){
            case 1:{
                int k,a,x;cin>>k>>a>>x,k--,a--;
                root[k]=modify(root[k],a,x);
            }break;
            case 2:{
                int k,a,b;cin>>k>>a>>b,k--,a--;
                cout<<query(root[k],a,b)<<endl;
            }break;
            case 3:{
                int k;cin>>k,k--;
                root.push_back(root[k]);     
            }break;
        }
    }
}
```

## old ver don't see

```cpp=
#include<iostream>
#include<vector>
#include<algorithm>
#include<numeric>
#include<limits>
#include<cmath>
using namespace std;
template<typename T>
ostream& operator<<(ostream& os,const vector<T>& v){
    for(const auto& i:v) os<<i<<' ';
    return os;
}
```
```cpp=
template<typename T>
struct segment_tree{
    const T limit;
    const size_t _size;
    vector<T> vec;
    const T& (*cmp)(const T&,const T&);
    const T operator()(size_t l,size_t r){
        if(l==r) return limit;
        if(l>r) swap(l,r);
        l+=_size,r+=_size;
        T ans=limit;
        while(l<r){
            if(l&1) ans=cmp(ans,vec[l++]);
            if(r&1) ans=cmp(ans,vec[--r]);
            l>>=1,r>>=1;
        }
        return ans;
    }
    void update(size_t pos,T x){
        pos+=_size,vec[pos]=x;
        while(pos!=1)vec[pos>>1]=cmp(vec[pos>>1],vec[pos]),pos>>=1;
    }
    segment_tree(const vector<T>& v,const T& (*c)(const T&,const T&)=
    [](const auto& a,const auto& b)->const decltype(a){return (a<b?a:b);}):
    limit((c(numeric_limits<T>::min(),numeric_limits<T>::max())==
    numeric_limits<T>::min()?numeric_limits<T>::max():numeric_limits<T>::min())),
    _size(v.size()),vec(_size<<1),cmp(c){
        for(size_t i=0;i!=_size;i++)
            vec[_size+i]=v[i];
        for(size_t i=_size-1;i;i--)
            vec[i]=cmp(vec[i<<1],vec[(i<<1)+1]);
    }
};
int main(){
	vector<int> vec{1,2,4,6,3,2,8,7,9,0};
	segment_tree<int> mintree(vec,[](const auto& a,const auto& b)->decltype(a){return (a<b?a:b);});
	segment_tree<int> maxtree(vec,[](const auto& a,const auto& b)->decltype(a){return (a>b?a:b);});
	cout<<mintree(1,10)<<endl;
	cout<<maxtree(1,10)<<endl;
	maxtree.update(5,20);
	cout<<maxtree.vec<<endl;
	cout<<maxtree(1,10)<<endl;
	return 0;
}
```

## another version
```cpp=
template<typename T>
struct segment_tree{
#define left(x) (x<<1)
#define right(x) ((x<<1)+1)
#define parent(x) (x>>1)
	T (*cmp)(T,T);
	vector<T> vec;const size_t _size;
	const T operator[](size_t pos){return vec[pos+_size];}
	T operator()(size_t l,size_t r){
		if(l>r) swap(l,r);
		l+=_size,r+=_size;
		T ans=vec[l];
		while(l<r){
			if(l&1) ans=cmp(ans,vec[l++]);
			if(r&1) ans=cmp(ans,vec[--r]);
			l=parent(l),r=parent(r);
		}
		return ans;
	}
	void update(size_t pos,T x){
		pos+=_size;
		vec[pos]=x;
		while(pos!=1){vec[parent(pos)]=cmp(vec[parent(pos)],vec[pos]);pos=parent(pos);}
	}
	segment_tree(const vector<T>& v,T (*c)(T,T)=[](auto a,auto b){return (a<b?a:b);}):cmp(c),vec(v.size()<<1,0),_size(v.size()){
		for(size_t t=_size;t!=(_size<<1);t++)
			vec[t]=v[t-_size];
		for(size_t t=_size-1;t;t--)
			vec[t]=cmp(vec[left(t)],vec[right(t)]);
	}
#undef left
#undef right
#undef parent
};
template<typename T>
ostream& operator<<(ostream& os,const vector<T>& v){
	for(const auto& i:v) os<<i<<' ';
	return os;
}
```

## third version

```cpp=
#include<iostream>
#include<vector>
#include<algorithm>
#include<limits>
using namespace std;
int lookup_popcnt(unsigned int n) {
# define BIT2(n) n      , n+1      , n+1      , n+2
# define BIT4(n) BIT2(n), BIT2(n+1), BIT2(n+1), BIT2(n+2)
# define BIT6(n) BIT4(n), BIT4(n+1), BIT4(n+1), BIT4(n+2)
# define BIT8(n) BIT6(n), BIT6(n+1), BIT6(n+1), BIT6(n+2)
	static constexpr unsigned char TABLE[256] = {BIT8(0)};
	return TABLE[n       & 0xff] +
	       TABLE[(n >> 8)  & 0xff] +
	       TABLE[(n >> 16) & 0xff] +
	       TABLE[(n >> 24) & 0xff];
}
inline size_t lchild(const size_t& n) {return n << 1;}
inline size_t rchild(const size_t& n) {return n << 1 | 1;}
inline size_t parent(const size_t& n) {return n >> 1;}
inline size_t sibling(const size_t& n) {return n ^ 1;}
struct segment_tree {
	const size_t size, height;
	vector<int> data, lazy;
	void apply(size_t pos, int val) {
		data[pos] += val;
		if (pos < size) lazy[pos] += val;
	}
	void push(int pos) {
		for (int s = height; s > 0; --s) {
			int i = pos >> s;
			if (lazy[i] != 0) {
				apply(lchild(i), lazy[i]);
				apply(rchild(i), lazy[i]);
				lazy[i] = 0;
			}
		}
	}
	int operator()(size_t l, size_t r) {
		int res = numeric_limits<int>::min();
		l += size, r += size;
		push(l), push(r - 1);
		for (; l < r; l >>= 1, r >>= 1) {
			if (l & 1) res = max(res, data[l++]);
			if (r & 1) res = max(res, data[--r]);
		}
		return res;
	}
	void build(size_t pos) {
		while (pos > 1)
			pos >>= 1, data[pos] = max(data[lchild(pos)], data[rchild(pos)]) + lazy[pos];
	}
	void increase(size_t l, size_t r, int val) {
		int l0 = l += size, r0 = r += size;
		for (; l < r; l >>= 1, r >>= 1) {
			if (l & 1) apply(l++, val);
			if (r & 1) apply(--r, val);
		}
		build(l0), build(r0 - 1);
	}
	void modify(size_t pos, int val) {
		for (data[pos += size] = val; pos > 1; pos >>= 1)
			data[parent(pos)] = max(data[pos], data[sibling(pos)]);
	}
	void init() {
		for (int i = size - 1; i > 0; --i)
			data[i] = max(data[lchild(i)], data[rchild(i)]);
	}
	segment_tree(const vector<int>& v):
		size(v.size()), height(lookup_popcnt(size)), data(2 * v.size()), lazy(size) {
		for (size_t i = 0; i != size; i++)
			data[i + size] = v[i];
		init();
	}
};
int main() {
	cin.tie(nullptr);
	ios::sync_with_stdio(false);
	int n, m, c; cin >> n >> m;
	vector<int> vec(n, 0);
	segment_tree tree(vec);
	size_t a, b;
	for (int i = 0; i != m; i++)
		cin >> a >> b >> c, tree.increase(a - 1, b, c);
	cout << tree(0, n);
	return 0;
}
```

## v4
```cpp=
#include<iostream>
#include<vector>
#include<algorithm>
#include<limits>
#define endl '\n'
using namespace std;
int lookup_popcnt(unsigned int n) {
# define BIT2(n) n      , n+1      , n+1      , n+2
# define BIT4(n) BIT2(n), BIT2(n+1), BIT2(n+1), BIT2(n+2)
# define BIT6(n) BIT4(n), BIT4(n+1), BIT4(n+1), BIT4(n+2)
# define BIT8(n) BIT6(n), BIT6(n+1), BIT6(n+1), BIT6(n+2)
	static constexpr unsigned char TABLE[256] = {BIT8(0)};
	return TABLE[n       & 0xff] +
	       TABLE[(n >> 8)  & 0xff] +
	       TABLE[(n >> 16) & 0xff] +
	       TABLE[(n >> 24) & 0xff];
}
inline size_t lchild(const size_t& n) {return n << 1;}
inline size_t rchild(const size_t& n) {return n << 1 | 1;}
inline size_t parent(const size_t& n) {return n >> 1;}
inline size_t sibling(const size_t& n) {return n ^ 1;}
template<class cmp = less<int>>
struct segment_tree {
	const size_t size, height;
	const int limit;
	vector<int> data, lazy;
	int max(const int& a, const int& b) {
		return cmp()(a, b) ? b : a;
	}
	void apply(size_t pos, int val) {
		data[pos] += val;
		if (pos < size) lazy[pos] += val;
	}
	void push(int pos) {
		for (int s = height; s > 0; --s) {
			int i = pos >> s;
			if (lazy[i] != 0) {
				apply(lchild(i), lazy[i]);
				apply(rchild(i), lazy[i]);
				lazy[i] = 0;
			}
		}
	}
	int operator()(size_t l, size_t r) {
		int res = limit;
		l += size, r += size;
		push(l), push(r - 1);
		for (; l < r; l >>= 1, r >>= 1) {
			if (l & 1) res = max(res, data[l++]);
			if (r & 1) res = max(res, data[--r]);
		}
		return res;
	}
	void build(size_t pos) {
		while (pos > 1)
			pos >>= 1, data[pos] = max(data[lchild(pos)], data[rchild(pos)]) + lazy[pos];
	}
	void increase(size_t l, size_t r, int val) {
		int l0 = l += size, r0 = r += size;
		for (; l < r; l >>= 1, r >>= 1) {
			if (l & 1) apply(l++, val);
			if (r & 1) apply(--r, val);
		}
		build(l0), build(r0 - 1);
	}
	void modify(size_t pos, int val) {
		for (data[pos += size] = val; pos > 1; pos >>= 1)
			data[parent(pos)] = max(data[pos], data[sibling(pos)]);
	}
	void init() {
		for (int i = size - 1; i > 0; --i)
			data[i] = max(data[lchild(i)], data[rchild(i)]);
	}
	segment_tree(const vector<int>& v):
		size(v.size()), height(lookup_popcnt(size)),
		limit(cmp()(numeric_limits<int>::min(), numeric_limits<int>::max()) ?
		      numeric_limits<int>::min() : numeric_limits<int>::max()),
		data(2 * v.size()), lazy(size) {
		for (size_t i = 0; i != size; i++)
			data[i + size] = v[i];
		init();
	}
};
ostream& operator<<(ostream& os, vector<auto>& v) {
	for (auto& i : v)
		cout << i << ' ';
	return os;
}
int main() {
	cin.tie(nullptr);
	ios::sync_with_stdio(false);
	int n, l, r; cin >> n;
	vector<int> v(n);
	for (auto& i : v) cin >> i;
	segment_tree<less<int>> mintree(v);
	segment_tree<greater<int>> maxtree(v);
	while (cin >> l >> r)
		cout << mintree(l - 1, r) + maxtree(l - 1, r) << endl;
	return 0;
}
```

## recursive ver
```cpp=
#include<iostream>
#include<vector>
#include<algorithm>
#include<climits>
#include<functional>
#define endl '\n'
using namespace std;
int main() {
	cin.tie(nullptr);
	ios::sync_with_stdio(false);
	int n, a, b; cin >> n;
	vector<pair<int, int>> seg(n << 2, {INT_MIN, INT_MAX});
	auto pull = [](auto a, auto b) -> pair<int, int> {
		return {max(a.first, b.first), min(a.second, b.second)};
	};
	auto lch = [](int x) {return (x << 1) + 1;};
	auto rch = [](int x) {return (x << 1) + 2;};
	auto modify = [&](int i, int x) {
		function<void(int, int, int)> _ = [&](int id, int l, int r) {
			if (l == r) {seg[id] = {x, x}; return;}
			int m = (long long)(l + r) >> 1;
			if (i <= m)
				_(lch(id), l, m);
			else
				_(rch(id), m + 1, r);
			seg[id] = pull(seg[lch(id)], seg[rch(id)]);
		}; _(0, 0, n - 1);
	};
	auto query = [&](int ql, int qr) {
		function<pair<int, int>(int, int, int)> _ = [&](int id, int l, int r) -> pair<int, int> {
			if (qr < l || r < ql) return {INT_MIN, INT_MAX};
			if (ql <= l && r <= qr) return seg[id];
			int m = (long long)(l + r) >> 1;
			return pull(_(lch(id), l, m), _(rch(id), m + 1, r));
		}; return _(0, 0, n - 1);
	};
	for (int i = 0, tmp; i != n; i++)
		cin >> tmp, modify(i, tmp);
	while (cin >> a >> b) {
		int p, q; tie(p, q) = query(a - 1, b - 1);
		cout << p + q << endl;
	}
	return 0;
}
```