---
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;
}
```