#include<cmath> #include<algorithm> #include<vector>
#ifndef _MINMAX_HEAP_ #define _MINMAX_HEAP_
// n == v.size() template< typename T > void make_minmax_heap( std::vector<T>& v ); // o(n) template< typename T > void pop_min_heap( std::vector<T>& v ); // o(log n) template< typename T > void pop_max_heap( std::vector<T>& v ); // o(log n) template< typename T > void push_minmax_heap( std::vector<T>& v, const T& dat ); // o(log n) template< typename T > const T& get_min_heap( const std::vector<T>& v ); // o(1) template< typename T > const T& get_max_heap( const std::vector<T>& v ); // o(1)
namespace // anónimo { template< typename T > void reset( const int& pos, const typename std::vector<T>::iterator& it, const int& n ); template< typename T > void sink( int i, int pos, const typename std::vector<T>::iterator& it, const int& n ); template< typename T > void swim( int i, const int& pos, const typename std::vector<T>::iterator& it, const int& n ); }
template< typename T > void make_minmax_heap( std::vector<T>& v ) { typename std::vector<T>::iterator it = v.begin() - 2; int n = v.size() + 2;
int pos = log(n-1)/M_LN2; pos = 1 << pos;
reset<T>( pos, it, n );
int m = pos; pos /= 2; while( pos > 1 ) { int i; reset<T>( pos, it, n );
for( i = pos; i < m; ++i ) sink<T>( i, pos, it, n );
m = pos; pos /= 2; } }
template< typename T > void pop_min_heap( std::vector<T>& v ) { typename std::vector<T>::iterator it = v.begin() - 2; int n = v.size() + 2;
it[2] = it[n-1]; sink<T>( 2, 2, it, n ); v.pop_back(); }
template< typename T > void pop_max_heap( std::vector<T>& v ) { typename std::vector<T>::iterator it = v.begin() - 2; int n = v.size() + 2;
it[3] = it[n-1]; sink<T>( 3, 2, it, n ); v.pop_back(); }
template< typename T > void push_minmax_heap( std::vector<T>& v, const T& dat ) { typename std::vector<int>::iterator it = v.begin() - 2; int n = v.size() + 2;
v.push_back(dat); int pos = log(n-1) / M_LN2; pos = 1 << pos;
swim<T>( n, pos, it, n ); }
template< typename T > inline const T& get_min_heap( const std::vector<T>& v ) { return v[0]; }
template< typename T > inline const T& get_max_heap( const std::vector<T>& v ) { return v.size() > 1 ? v[1] : v[0]; }
namespace // anónimo { template< typename T > void reset( const int& pos, const typename std::vector<T>::iterator& it, const int& n ) { int inc = pos/2; int m = pos + inc; if( m > n ) m = n;
for( int i = pos; i < m; ++i ) { // calcular k, hermano de i int k = i+inc; if( k >= n ) k /= 2;
// intercambiar si hace falta if( it[i] > it[k] ) std::swap( it[i], it[k] ); } }
template< typename T > void sink( int i, int pos, const typename std::vector<T>::iterator& it, const int& n ) { int j = 2*i; int k;
while( j < n ) { k = j + 1;
if( j & pos ) //está en el maxheap { if( k < n && it[j] < it[k] ) j++; if( it[i] < it[j] ) { std::swap( it[i], it[j] );
k = j - pos; if( it[k] > it[j] ) std::swap( it[j] , it[k] );
// caso especial si j tiene más de 1 hermano en minheap int a = 2*j; int b = 2*k; if( a >= n && b < n ) k = b; b++; if( a+1 >= n && b < n && it[b] > it[k] ) k = b;
if( it[k] > it[j] ) std::swap( it[j], it[k] ); } } else // está en el minheap { if( k < n && it[j] > it[k] ) j++; if( it[i] > it[j] ) { std::swap( it[i], it[j] );
k = j + pos; if( k >= n ) k /= 2; if( it[j] > it[k] ) std::swap( it[j], it[k] ); } }
i = j; j = 2*i; pos *= 2; } }
template< typename T > void swim( int i, const int& pos, const typename std::vector<T>::iterator& it, const int& n ) { bool b; int j; int inc = pos/2; if( b = (i & inc) ) // está en maxheap { j = i - inc; if( it[j] > it[i] ) { std::swap( it[j], it[i] ); i = j; b = false; } } else //está en minheap { j = i + inc; if( j >= n ) j /= 2; if( it[i] > it[j] ) { std::swap( it[j], it[i] ); i = j; b = true; } }
j = i/2; if( b ) { while( j > 1 && it[j] < it[i] ) { std::swap( it[j], it[i] ); i = j; j /= 2; } } else { while( j > 1 && it[j] > it[i] ) { std::swap( it[j], it[i] ); i = j; j /= 2; } } }
}
#endif |