#include <iostream>
#include <iomanip>
#include <algorithm>

using namespace std;

class MinStack
{
private:
    int * stk;
    size_t capacity, size_;
    int m = 0;
    void resize_()
    {
        if (capacity == size_)
        {
            int * tmp = new int[capacity *= 2];
            for(size_t i = 0; i < size_; ++i)
                tmp[i] = stk[i];
            delete[] stk;
            stk = tmp;
        }
    }
    void swap(MinStack& s)
    {
        std::swap(stk,s.stk);
        std::swap(capacity,s.capacity);
        std::swap(size_,s.size_);
        std::swap(m,s.m);
    }
public:
    MinStack(size_t sz = 16):stk(new int[sz+1]),capacity(sz+1),size_(0){}
    ~MinStack()
    {
        delete[] stk;
    }
    MinStack(const MinStack& s):stk(new int[s.size_]),capacity(s.size_)
        ,size_(s.size_),m(s.m)
    {
        for(size_t i = 0; i < s.size_; ++i)
            stk[i] = s.stk[i];
    }
    MinStack& operator = (const MinStack& s)
    {
        MinStack tmp(s);
        swap(tmp);
        return *this;
    }

    void push(int i)
    {
        resize_();
        m = (size_ == 0) ? i : std::min(m,i);
        stk[size_++] = i;
    }
    bool empty() const
    {
        return size_ == 0;
    }
    int pop()
    {
        if (empty()) throw runtime_error("pop from empty stack");
        int r = stk[--size_];
        if (r == m && size_) m = *std::min_element(stk,stk+size_);
        return r;
    }
    int min() const
    {
        if (empty()) throw runtime_error("min from empty stack");
        return m;
    }
    int back() const
    {
        if (empty()) throw runtime_error("back from empty stack");
        return stk[size_-1];
    }
    void clear()
    {
        size_ = 0;
    }
    size_t size() const { return size_; }
};

int main()
{
    MinStack s;
    for(int i = 0; i < 20; ++i)
    {
        int d = rand()%90+10;
        cout << d << "  ";
        s.push(d);
    }
    cout << endl;

    for(int i = 0; i < 20; ++i)
    {
        cout << setw(2) << s.size() << ": " << s.min() << "  ";
        cout << s.pop() << endl;
    }
}
