<tb@panthema.net>
<http://www.gnu.org/licenses/>
template <typename offset_type, typename value_type>
class RMQ_Stack
{
private:
struct Item {
offset_type index;
value_type minimum;
Item(const offset_type& i, const value_type& m)
: index(i), minimum(m) {}
};
typedef typename std::vector<Item> itemlist_type;
typedef typename itemlist_type::iterator itemiter_type;
typedef typename itemlist_type::const_iterator itemciter_type;
offset_type m_right;
itemlist_type m_stack;
static bool ItemCmpIndex(const Item& i, const offset_type& index) {
return i.index < index;
}
static bool ItemCmpMinimum(const Item& i, const value_type& m) {
return i.minimum < m;
}
public:
RMQ_Stack()
: m_right(0)
{
}
void set(const offset_type& index, const value_type& val)
{
assert( m_right <= index );
itemiter_type p = std::lower_bound(m_stack.begin(), m_stack.end(), val, ItemCmpMinimum);
m_stack.erase(p, m_stack.end());
m_stack.push_back( Item(index,val) );
m_right = index+1;
}
const value_type& query(const offset_type& left, const offset_type& right) const
{
assert(right+1 == m_right);
assert(left <= m_right);
stxxl::STXXL_UNUSED(right);
itemciter_type p = std::lower_bound(m_stack.begin(), m_stack.end(), left, ItemCmpIndex);
return p->minimum;
}
const value_type& global_minimum() const
{
assert(m_stack.size());
return m_stack.front().minimum;
}
void clear()
{
m_right = 0;
m_stack.clear();
}
size_t memsize() const
{
return m_stack.capacity() * sizeof(m_stack[0]) + sizeof(*this);
}
void print()
{
std::cout << "Stack: ";
for (itemiter_type i = m_stack.begin(); i != m_stack.end(); ++i)
{
std::cout << "(" << i->index << "," << i->minimum << ") ";
}
std::cout << "\n";
}
};
template <typename offset_type, typename value_type, size_t slabsize>
class RMQ_Stack_Blocked
{
private:
RMQ_Stack<offset_type,value_type> rmq_near;
RMQ_Stack<offset_type,value_type> rmq_slabs;
offset_type thisslab;
public:
RMQ_Stack_Blocked()
: thisslab(0)
{
}
void set(const offset_type& index, const value_type& val)
{
assert(index >= thisslab);
if (index >= offset_type(thisslab + slabsize))
{
thisslab = (offset_type)(index / slabsize) * slabsize;
rmq_slabs.set(thisslab-1, rmq_near.global_minimum());
rmq_near.clear();
}
rmq_near.set(index, val);
}
const value_type& query(const offset_type& left, const offset_type& right) const
{
if (left >= thisslab)
{
return rmq_near.query(left,right);
}
else
{
assert( left % slabsize == 0 );
const value_type& min1 = rmq_slabs.query(left, thisslab-1);
const value_type& min2 = rmq_near.query(thisslab, right);
return (min1 < min2) ? min1 : min2;
}
}
void print_size()
{
std::cout << "RMQ_near: " << rmq_near.memsize() << " + RMQ_slabs: " << rmq_slabs.memsize() << "\n";
}
};