Skip to content

Instantly share code, notes, and snippets.

@tanitanin
Created December 19, 2014 17:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tanitanin/0453540e7eaa882f61d0 to your computer and use it in GitHub Desktop.
Save tanitanin/0453540e7eaa882f61d0 to your computer and use it in GitHub Desktop.
Segment Tree for range add and minimum query
#pragma once
#include <vector>
#include <algorithm>
#include <limits>
template<class T>
class starrysky {
public:
struct node { T add; T min; };
explicit starrysky(size_t N=1, T add_init=0, T min_init=std::numeric_limits<T>::max())
: _add_init(add_init), _min_init(min_init), _N(N), _tree(2*N-1,{add_init,add_init}) {}
void add(size_t i, size_t j, T data) {
_add(i,j,data,0,0,_N);
}
T min(size_t i, size_t j) {
return _min(i,j,0,0,_N);
}
private:
void _add(size_t i, size_t j, T data, size_t k, size_t l, size_t r) {
if(j <= l || r <= i) return;
if(i <= l && r <= j) {
_tree[k].add += data;
while(k>0) {
k = (k - 1) / 2;
const T vleft = _tree[2*k+1].min + _tree[2*k+1].add;
const T vright = _tree[2*k+2].min + _tree[2*k+2].add;
_tree[k].min = std::min(vleft, vright);
}
} else {
_add(i,j,data,k*2+1,l,(l+r)/2);
_add(i,j,data,k*2+2,(l+r)/2,r);
}
}
T _min(size_t i, size_t j, size_t k, size_t l, size_t r) {
if(r <= i || j <= l) return _min_init;
if(i <= l && r <= j) return _tree[k].min + _tree[k].add;
else {
const T vleft = _min(i,j,k*2+1,l,(l+r)/2);
const T vright = _min(i,j,k*2+2,(l+r)/2,r);
return std::min(vleft,vright) + _tree[k].add;
}
}
private:
T _add_init, _min_init;
size_t _N;
std::vector<node> _tree;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment