// tree internal header

#if     _MSC_VER > 1000
#pragma once
#endif

#ifndef _XTREE_
#define _XTREE_

#pragma message ("Using modified VC6 XTREE for Falcon...")

#include <cstddef>
#include <iterator>
#include <memory>
#include <xutility>

#define _IsNil( x ) (_Left(x) == 0)
#define _IsNotNil( x ) (_Left(x) != 0)

#ifdef  _MSC_VER
#pragma pack(push,8)
#endif  /* _MSC_VER */
_STD_BEGIN
                // TEMPLATE CLASS _Tree
template<class _K, class _Ty, class _Kfn, class _Pr, class _A>
        class _Tree {
protected:
        enum _Redbl {_Red, _Black};
        struct _Node;
        friend struct _Node;
        typedef _POINTER_X(_Node, _A) _Nodeptr;
        struct _Node {
                _Nodeptr _Left, _Parent, _Right;
                _Ty _Value;
                _Redbl _Color;
                };
        typedef _REFERENCE_X(_Nodeptr, _A) _Nodepref;
        typedef _REFERENCE_X(const _K, _A) _Keyref;
        typedef _REFERENCE_X(_Redbl, _A) _Rbref;
        typedef _REFERENCE_X(_Ty, _A) _Vref;
        static _Rbref _Color(_Nodeptr _P)
                {return ((_Rbref)(*_P)._Color); }
        static _Keyref _Key(_Nodeptr _P)
                {return (_Kfn()(_Value(_P))); }
        static _Nodepref _Left(_Nodeptr _P)
                {return ((_Nodepref)(*_P)._Left); }
        static _Nodepref _Parent(_Nodeptr _P)
                {return ((_Nodepref)(*_P)._Parent); }
        static _Nodepref _Right(_Nodeptr _P)
                {return ((_Nodepref)(*_P)._Right); }
        static _Vref _Value(_Nodeptr _P)
                {return ((_Vref)(*_P)._Value); }
public:
        typedef _Tree<_K, _Ty, _Kfn, _Pr, _A> _Myt;
        typedef _K key_type;
        typedef _Ty value_type;
        typedef _A::size_type size_type;
        typedef _A::difference_type difference_type;
        typedef _POINTER_X(_Ty, _A) _Tptr;
        typedef _POINTER_X(const _Ty, _A) _Ctptr;
        typedef _REFERENCE_X(_Ty, _A) reference;
        typedef _REFERENCE_X(const _Ty, _A) const_reference;
                // CLASS const_iterator
        class iterator;
        class const_iterator;
        friend class const_iterator;
        class const_iterator : public _Bidit<_Ty, difference_type> {
        public:
                const_iterator()
                        {}
                const_iterator(_Nodeptr _P)
                        : _Ptr(_P) {}
                const_iterator(const iterator& _X)
                        : _Ptr(_X._Ptr) {}
                const_reference operator*() const
                        {return (_Value(_Ptr)); }
                _Ctptr operator->() const
                        {return (&**this); }
                const_iterator& operator++()
                        {_Inc();
                        return (*this); }
                const_iterator operator++(int)
                        {const_iterator _Tmp = *this;
                        ++*this;
                        return (_Tmp); }
                const_iterator& operator--()
                        {_Dec();
                        return (*this); }
                const_iterator operator--(int)
                        {const_iterator _Tmp = *this;
                        --*this;
                        return (_Tmp); }
                bool operator==(const const_iterator& _X) const
                        {return (_Ptr == _X._Ptr); }
                bool operator!=(const const_iterator& _X) const
                        {return (!(*this == _X)); }
                void _Dec()
                        {if (_Color(_Ptr) == _Red
                                && _Parent(_Parent(_Ptr)) == _Ptr)
                                _Ptr = _Right(_Ptr);
                        /* JC else if (_Left(_Ptr) != _Nil) */
                        else if ( _IsNotNil(_Left(_Ptr)) )
                                _Ptr = _Max(_Left(_Ptr));
                        else
                                {_Nodeptr _P;
                                while (_Ptr == _Left(_P = _Parent(_Ptr)))
                                        _Ptr = _P;
                                _Ptr = _P; }}
                void _Inc()
                        {/* JC if (_Right(_Ptr) != _Nil)*/
                         if ( _IsNotNil(_Right(_Ptr)) ) 
                                _Ptr = _Min(_Right(_Ptr));
                        else
                                {_Nodeptr _P;
                                while (_Ptr == _Right(_P = _Parent(_Ptr)))
                                        _Ptr = _P;
                                if (_Right(_Ptr) != _P)
                                        _Ptr = _P; }}
                _Nodeptr _Mynode() const
                        {return (_Ptr); }
        protected:
                _Nodeptr _Ptr;
                };
                // CLASS iterator
        friend class iterator;
        class iterator : public const_iterator {
        public:
                iterator()
                        {}
                iterator(_Nodeptr _P)
                        : const_iterator(_P) {}
                reference operator*() const
                        {return (_Value(_Ptr)); }
                _Tptr operator->() const
                        {return (&**this); }
                iterator& operator++()
                        {_Inc();
                        return (*this); }
                iterator operator++(int)
                        {iterator _Tmp = *this;
                        ++*this;
                        return (_Tmp); }
                iterator& operator--()
                        {_Dec();
                        return (*this); }
                iterator operator--(int)
                        {iterator _Tmp = *this;
                        --*this;
                        return (_Tmp); }
                bool operator==(const iterator& _X) const
                        {return (_Ptr == _X._Ptr); }
                bool operator!=(const iterator& _X) const
                        {return (!(*this == _X)); }
                };
        typedef reverse_bidirectional_iterator<iterator,
                value_type, reference, _Tptr, difference_type>
                        reverse_iterator;
        typedef reverse_bidirectional_iterator<const_iterator,
                value_type, const_reference, _Ctptr, difference_type>
                        const_reverse_iterator;
        typedef pair<iterator, bool> _Pairib;
        typedef pair<iterator, iterator> _Pairii;
        typedef pair<const_iterator, const_iterator> _Paircc;
        explicit _Tree(const _Pr& _Parg, bool _Marg = true,
                const _A& _Al = _A())
                : allocator(_Al),
                key_compare(_Parg), _Multi(_Marg)
                {_Init(); }
        _Tree(const _Ty *_F, const _Ty *_L,
                const _Pr& _Parg, bool _Marg = true,
                const _A& _Al = _A())
                : allocator(_Al),
                key_compare(_Parg), _Multi(_Marg)
                {_Init();
                insert(_F, _L); }
        _Tree(const _Myt& _X)
                : allocator(_X.allocator),
                key_compare(_X.key_compare), _Multi(_X._Multi)
                {_Init();
                _Copy(_X); }
        ~_Tree()
                {erase(begin(), end());
                _Freenode(_Head);
                _Head = 0, _Size = 0;
                _Nodeptr _Tmp = 0;
                        {_Lockit _Lk;
                        if (--_Nilrefs == 0)
                                {_Tmp = _Nil;
                                _Nil = 0; }}
                if (_Tmp != 0)
                        _Freenode(_Tmp); }
        _Myt& operator=(const _Myt& _X)
                {if (this != &_X)
                        {erase(begin(), end());
                        key_compare = _X.key_compare;
                        _Copy(_X); }
                return (*this); }
        iterator begin()
                {return (iterator(_Lmost())); }
        const_iterator begin() const
                {return (const_iterator(_Lmost())); }
        iterator end()
                {return (iterator(_Head)); }
        const_iterator end() const
                {return (const_iterator(_Head)); }
        reverse_iterator rbegin()
                {return (reverse_iterator(end())); }
        const_reverse_iterator rbegin() const
                {return (const_reverse_iterator(end())); }
        reverse_iterator rend()
                {return (reverse_iterator(begin())); }
        const_reverse_iterator rend() const
                {return (const_reverse_iterator(begin())); }
        size_type size() const
                {return (_Size); }
        size_type max_size() const
                {return (allocator.max_size()); }
        bool empty() const
                {return (size() == 0); }
        _A get_allocator() const
                {return (allocator); }
        _Pr key_comp() const
                {return (key_compare); }
        _Pairib insert(const value_type& _V)
                {_Nodeptr _X = _Root();
                _Nodeptr _Y = _Head;
                bool _Ans = true;
                        /* JC while (_X != _Nil) */
                        while( _IsNotNil(_X) )
                                {_Y = _X;
                                _Ans = key_compare(_Kfn()(_V), _Key(_X));
                                _X = _Ans ? _Left(_X) : _Right(_X); }
                if (_Multi)
                        return (_Pairib(_Insert(_X, _Y, _V), true));
                iterator _P = iterator(_Y);
                if (!_Ans)
                        ;
                else if (_P == begin())
                        return (_Pairib(_Insert(_X, _Y, _V), true));
                else
                        --_P;
                if (key_compare(_Key(_P._Mynode()), _Kfn()(_V)))
                        return (_Pairib(_Insert(_X, _Y, _V), true));
                return (_Pairib(_P, false)); }
        iterator insert(iterator _P, const value_type& _V)
                {if (size() == 0)
                        ;
                else if (_P == begin())
                        {if (key_compare(_Kfn()(_V), _Key(_P._Mynode())))
                                return (_Insert(_Head, _P._Mynode(), _V)); }
                else if (_P == end())
                        {if (key_compare(_Key(_Rmost()), _Kfn()(_V)))
                                return (_Insert(_Nil, _Rmost(), _V)); }
                else
                        {iterator _Pb = _P;
                        if (key_compare(_Key((--_Pb)._Mynode()), _Kfn()(_V))
                                && key_compare(_Kfn()(_V), _Key(_P._Mynode())))
                                { /* JC if (_Right(_Pb._Mynode()) == _Nil) */
                                  if ( _IsNil(_Right(_Pb._Mynode())) )
                                        return (_Insert(_Nil, _Pb._Mynode(), _V));
                                else
                                        return (_Insert(_Head, _P._Mynode(), _V)); }}
                return (insert(_V).first); }
        void insert(iterator _F, iterator _L)
                {for (; _F != _L; ++_F)
                        insert(*_F); }
        void insert(const value_type *_F, const value_type *_L)
                {for (; _F != _L; ++_F)
                        insert(*_F); }
        iterator erase(iterator _P)
                {_Nodeptr _X;
                _Nodeptr _Y = (_P++)._Mynode();
                _Nodeptr _Z = _Y;
                /* JC if (_Left(_Y) == _Nil) */
                if ( _IsNil(_Left(_Y)) )
                        _X = _Right(_Y);
                /* JC else if (_Right(_Y) == _Nil) */
                else if (_IsNil(_Right(_Y)))
                        _X = _Left(_Y);
                else
                        _Y = _Min(_Right(_Y)), _X = _Right(_Y);
                { _Lockit _Lk;
                if (_Y != _Z)
                        {_Parent(_Left(_Z)) = _Y;
                        _Left(_Y) = _Left(_Z);
                        if (_Y == _Right(_Z))
                                _Parent(_X) = _Y;
                        else
                                {_Parent(_X) = _Parent(_Y);
                                _Left(_Parent(_Y)) = _X;
                                _Right(_Y) = _Right(_Z);
                                _Parent(_Right(_Z)) = _Y; }
                        if (_Root() == _Z)
                                _Root() = _Y;
                        else if (_Left(_Parent(_Z)) == _Z)
                                _Left(_Parent(_Z)) = _Y;
                        else
                                _Right(_Parent(_Z)) = _Y;
                        _Parent(_Y) = _Parent(_Z);
                        std::swap(_Color(_Y), _Color(_Z));
                        _Y = _Z; }
                else
                        {_Parent(_X) = _Parent(_Y);
                        if (_Root() == _Z)
                                _Root() = _X;
                        else if (_Left(_Parent(_Z)) == _Z)
                                _Left(_Parent(_Z)) = _X;
                        else
                                _Right(_Parent(_Z)) = _X;
                        if (_Lmost() != _Z)
                                ;
                        /* JC else if (_Right(_Z) == _Nil) */
                        else if ( _IsNil(_Right(_Z)) )
                                _Lmost() = _Parent(_Z);
                        else
                                _Lmost() = _Min(_X);
                        if (_Rmost() != _Z)
                                ;
                        /* JC else if (_Left(_Z) == _Nil) */
                        else if ( _IsNil(_Left(_Z)) )
                                _Rmost() = _Parent(_Z);
                        else
                                _Rmost() = _Max(_X); }
                if (_Color(_Y) == _Black)
                        {while (_X != _Root() && _Color(_X) == _Black)
                                if (_X == _Left(_Parent(_X)))
                                        {_Nodeptr _W = _Right(_Parent(_X));
                                        if (_Color(_W) == _Red)
                                                {_Color(_W) = _Black;
                                                _Color(_Parent(_X)) = _Red;
                                                _Lrotate(_Parent(_X));
                                                _W = _Right(_Parent(_X)); }
                                        if (_Color(_Left(_W)) == _Black
                                                && _Color(_Right(_W)) == _Black)
                                                {_Color(_W) = _Red;
                                                _X = _Parent(_X); }
                                        else
                                                {if (_Color(_Right(_W)) == _Black)
                                                        {_Color(_Left(_W)) = _Black;
                                                        _Color(_W) = _Red;
                                                        _Rrotate(_W);
                                                        _W = _Right(_Parent(_X)); }
                                                _Color(_W) = _Color(_Parent(_X));
                                                _Color(_Parent(_X)) = _Black;
                                                _Color(_Right(_W)) = _Black;
                                                _Lrotate(_Parent(_X));
                                                break; }}
                                else
                                        {_Nodeptr _W = _Left(_Parent(_X));
                                        if (_Color(_W) == _Red)
                                                {_Color(_W) = _Black;
                                                _Color(_Parent(_X)) = _Red;
                                                _Rrotate(_Parent(_X));
                                                _W = _Left(_Parent(_X)); }
                                        if (_Color(_Right(_W)) == _Black
                                                && _Color(_Left(_W)) == _Black)
                                                {_Color(_W) = _Red;
                                                _X = _Parent(_X); }
                                        else
                                                {if (_Color(_Left(_W)) == _Black)
                                                        {_Color(_Right(_W)) = _Black;
                                                        _Color(_W) = _Red;
                                                        _Lrotate(_W);
                                                        _W = _Left(_Parent(_X)); }
                                                _Color(_W) = _Color(_Parent(_X));
                                                _Color(_Parent(_X)) = _Black;
                                                _Color(_Left(_W)) = _Black;
                                                _Rrotate(_Parent(_X));
                                                break; }}
                        _Color(_X) = _Black; }
                }
                _Destval(&_Value(_Y));
                _Freenode(_Y);
                --_Size;
                return (_P); }
        iterator erase(iterator _F, iterator _L)
                {if (size() == 0 || _F != begin() || _L != end())
                        {while (_F != _L)
                                erase(_F++);
                        return (_F); }
                else
                        {_Erase(_Root());
                        _Root() = _Nil, _Size = 0;
                        _Lmost() = _Head, _Rmost() = _Head;
                        return (begin()); }}
        size_type erase(const _K& _X)
                {_Pairii _P = equal_range(_X);
                size_type _N = 0;
                _Distance(_P.first, _P.second, _N);
                erase(_P.first, _P.second);
                return (_N); }
        void erase(const _K *_F, const _K *_L)
                {for (; _F != _L; ++_F)
                        erase(*_F); }
        void clear()
                {erase(begin(), end()); }
        iterator find(const _K& _Kv)
                {iterator _P = lower_bound(_Kv);
                return (_P == end()
                        || key_compare(_Kv, _Key(_P._Mynode()))
                                ? end() : _P); }
        const_iterator find(const _K& _Kv) const
                {const_iterator _P = lower_bound(_Kv);
                return (_P == end()
                        || key_compare(_Kv, _Key(_P._Mynode()))
                                ? end() : _P); }
        size_type count(const _K& _Kv) const
                {_Paircc _Ans = equal_range(_Kv);
                size_type _N = 0;
                _Distance(_Ans.first, _Ans.second, _N);
                return (_N); }
        iterator lower_bound(const _K& _Kv)
                {return (iterator(_Lbound(_Kv))); }
        const_iterator lower_bound(const _K& _Kv) const
                {return (const_iterator(_Lbound(_Kv))); }
        iterator upper_bound(const _K& _Kv)
                {return (iterator(_Ubound(_Kv))); }
        const_iterator upper_bound(const _K& _Kv) const
                {return (iterator(_Ubound(_Kv))); }
        _Pairii equal_range(const _K& _Kv)
                {return (_Pairii(lower_bound(_Kv), upper_bound(_Kv))); }
        _Paircc equal_range(const _K& _Kv) const
                {return (_Paircc(lower_bound(_Kv), upper_bound(_Kv))); }
        void swap(_Myt& _X)
                {std::swap(key_compare, _X.key_compare);
                if (allocator == _X.allocator)
                        {std::swap(_Head, _X._Head);
                        std::swap(_Multi, _X._Multi);
                        std::swap(_Size, _X._Size); }
                else
                        {_Myt _Ts = *this; *this = _X, _X = _Ts; }}
        friend void swap(_Myt& _X, _Myt& _Y)
                {_X.swap(_Y); }
protected:
        static _Nodeptr _Nil;
        static size_t _Nilrefs;
        void _Copy(const _Myt& _X)
                {_Root() = _Copy(_X._Root(), _Head);
                _Size = _X.size();
                /* JC if (_Root() != _Nil ) */
                if ( _IsNotNil(_Root()) )
                        {_Lmost() = _Min(_Root());
                        _Rmost() = _Max(_Root()); }
                else
                        _Lmost() = _Head, _Rmost() = _Head; }
        _Nodeptr _Copy(_Nodeptr _X, _Nodeptr _P)
                {_Nodeptr _R = _X;
                /* JC1 for (; _X != _Nil; _X = _Left(_X)) */
                for (; _IsNotNil(_X); _X = _Left(_X))
                        {_Nodeptr _Y = _Buynode(_P, _Color(_X));
                        if (_R == _X)
                                _R = _Y;
                        _Right(_Y) = _Copy(_Right(_X), _Y);
                        _Consval(&_Value(_Y), _Value(_X));
                        _Left(_P) = _Y;
                        _P = _Y; }
                _Left(_P) = _Nil;
                return (_R); }
        void _Erase(_Nodeptr _X)
                {/* JC for (_Nodeptr _Y = _X; _Y != _Nil; _X = _Y) */
                for (_Nodeptr _Y = _X; _IsNotNil(_Y); _X = _Y)
                        {_Erase(_Right(_Y));
                        _Y = _Left(_Y);
                        _Destval(&_Value(_X));
                        _Freenode(_X); }}
        void _Init()
                {_Nodeptr _Tmp = _Buynode(0, _Black);
                {_Lockit _Lk;
                if (_Nil == 0)
                                {_Nil = _Tmp;
                                _Tmp = 0;
                        _Left(_Nil) = 0, _Right(_Nil) = 0; }
                        ++_Nilrefs;  } 
                if (_Tmp != 0)
                        _Freenode(_Tmp);
                _Head = _Buynode(_Nil, _Red), _Size = 0;
                _Lmost() = _Head, _Rmost() = _Head; }
        iterator _Insert(_Nodeptr _X, _Nodeptr _Y, const _Ty& _V)
                {_Nodeptr _Z = _Buynode(_Y, _Red);
                _Left(_Z) = _Nil, _Right(_Z) = _Nil;
                _Consval(&_Value(_Z), _V);
                ++_Size;
                /* JC if (_Y == _Head || _X != _Nil */
               if (_Y == _Head || _IsNotNil(_X)
                        || key_compare(_Kfn()(_V), _Key(_Y)))
                        {_Left(_Y) = _Z;
                        if (_Y == _Head)
                                {_Root() = _Z;
                                _Rmost() = _Z; }
                        else if (_Y == _Lmost())
                                _Lmost() = _Z; }
                else
                        {_Right(_Y) = _Z;
                        if (_Y == _Rmost())
                                _Rmost() = _Z; }
                for (_X = _Z; _X != _Root()
                        && _Color(_Parent(_X)) == _Red; )
                        if (_Parent(_X) == _Left(_Parent(_Parent(_X))))
                                {_Y = _Right(_Parent(_Parent(_X)));
                                if (_Color(_Y) == _Red)
                                        {_Color(_Parent(_X)) = _Black;
                                        _Color(_Y) = _Black;
                                        _Color(_Parent(_Parent(_X))) = _Red;
                                        _X = _Parent(_Parent(_X)); }
                                else
                                        {if (_X == _Right(_Parent(_X)))
                                                {_X = _Parent(_X);
                                                _Lrotate(_X); }
                                        _Color(_Parent(_X)) = _Black;
                                        _Color(_Parent(_Parent(_X))) = _Red;
                                        _Rrotate(_Parent(_Parent(_X))); }}
                        else
                                {_Y = _Left(_Parent(_Parent(_X)));
                                if (_Color(_Y) == _Red)
                                        {_Color(_Parent(_X)) = _Black;
                                        _Color(_Y) = _Black;
                                        _Color(_Parent(_Parent(_X))) = _Red;
                                        _X = _Parent(_Parent(_X)); }
                                else
                                        {if (_X == _Left(_Parent(_X)))
                                                {_X = _Parent(_X);
                                                _Rrotate(_X); }
                                        _Color(_Parent(_X)) = _Black;
                                        _Color(_Parent(_Parent(_X))) = _Red;
                                        _Lrotate(_Parent(_Parent(_X))); }}
                _Color(_Root()) = _Black;
                return (iterator(_Z)); }
        _Nodeptr _Lbound(const _K& _Kv) const
                {_Nodeptr _X = _Root();
                _Nodeptr _Y = _Head;
                /* JC while (_X != _Nil) */
                while ( _IsNotNil(_X) )
                        if (key_compare(_Key(_X), _Kv))
                                _X = _Right(_X);
                        else
                                _Y = _X, _X = _Left(_X);
                return (_Y); }
        _Nodeptr& _Lmost()
                {return (_Left(_Head)); }
        _Nodeptr& _Lmost() const
                {return (_Left(_Head)); }
        void _Lrotate(_Nodeptr _X)
                {_Nodeptr _Y = _Right(_X);
                _Right(_X) = _Left(_Y);
                /* JC if (_Left(_Y) != _Nil) */
                if ( _IsNotNil(_Left(_Y)) )
                        _Parent(_Left(_Y)) = _X;
                _Parent(_Y) = _Parent(_X);
                if (_X == _Root())
                        _Root() = _Y;
                else if (_X == _Left(_Parent(_X)))
                        _Left(_Parent(_X)) = _Y;
                else
                        _Right(_Parent(_X)) = _Y;
                _Left(_Y) = _X;
                _Parent(_X) = _Y; }
        static _Nodeptr _Max(_Nodeptr _P)
                {/* JC while (_Right(_P) != _Nil) */
                  while ( _IsNotNil(_Right(_P)) )
                        _P = _Right(_P);
                return (_P); }
        static _Nodeptr _Min(_Nodeptr _P)
                {/* JC while (_Left(_P) != _Nil) */
                  while ( _IsNotNil(_Left(_P)) )
                        _P = _Left(_P);
                return (_P); }
        _Nodeptr& _Rmost()
                {return (_Right(_Head)); }
        _Nodeptr& _Rmost() const
                {return (_Right(_Head)); }
        _Nodeptr& _Root()
                {return (_Parent(_Head)); }
        _Nodeptr& _Root() const
                {return (_Parent(_Head)); }
        void _Rrotate(_Nodeptr _X)
                {_Nodeptr _Y = _Left(_X);
                _Left(_X) = _Right(_Y);
                /* JC1 if (_Right(_Y) != _Nil) */
                  if ( _IsNotNil( _Right(_Y) ))
                        _Parent(_Right(_Y)) = _X;
                _Parent(_Y) = _Parent(_X);
                if (_X == _Root())
                        _Root() = _Y;
                else if (_X == _Right(_Parent(_X)))
                        _Right(_Parent(_X)) = _Y;
                else
                        _Left(_Parent(_X)) = _Y;
                _Right(_Y) = _X;
                _Parent(_X) = _Y; }
        _Nodeptr _Ubound(const _K& _Kv) const
                {_Nodeptr _X = _Root();
                _Nodeptr _Y = _Head;
                /* JC while (_X != _Nil) */
                while ( _IsNotNil(_X) )
                        if (key_compare(_Kv, _Key(_X)))
                                _Y = _X, _X = _Left(_X);
                        else
                                _X = _Right(_X);
                return (_Y); }
        _Nodeptr _Buynode(_Nodeptr _Parg, _Redbl _Carg)
                {_Nodeptr _S = (_Nodeptr)allocator._Charalloc(
                        1 * sizeof (_Node));
                _Parent(_S) = _Parg;
                _Color(_S) = _Carg;
                return (_S); }
        void _Consval(_Tptr _P, const _Ty& _V)
                {_Construct(&*_P, _V); }
        void _Destval(_Tptr _P)
                {_Destroy(&*_P); }
        void _Freenode(_Nodeptr _S)
                {allocator.deallocate(_S, 1); }
        _A allocator;
        _Pr key_compare;
        _Nodeptr _Head;
        bool _Multi;
        size_type _Size;
        };
template<class _K, class _Ty, class _Kfn, class _Pr, class _A>
        _Tree<_K, _Ty, _Kfn, _Pr, _A>::_Nodeptr
                _Tree<_K, _Ty, _Kfn, _Pr, _A>::_Nil = 0;
template<class _K, class _Ty, class _Kfn, class _Pr, class _A>
        size_t _Tree<_K, _Ty, _Kfn, _Pr, _A>::_Nilrefs = 0;
                // tree TEMPLATE OPERATORS
template<class _K, class _Ty, class _Kfn,
        class _Pr, class _A> inline
        bool operator==(const _Tree<_K, _Ty, _Kfn, _Pr, _A>& _X,
                const _Tree<_K, _Ty, _Kfn, _Pr, _A>& _Y)
        {return (_X.size() == _Y.size()
                && equal(_X.begin(), _X.end(), _Y.begin())); }
template<class _K, class _Ty, class _Kfn,
        class _Pr, class _A> inline
        bool operator!=(const _Tree<_K, _Ty, _Kfn, _Pr, _A>& _X,
                const _Tree<_K, _Ty, _Kfn, _Pr, _A>& _Y)
        {return (!(_X == _Y)); }
template<class _K, class _Ty, class _Kfn,
        class _Pr, class _A> inline
        bool operator<(const _Tree<_K, _Ty, _Kfn, _Pr, _A>& _X,
                const _Tree<_K, _Ty, _Kfn, _Pr, _A>& _Y)
        {return (lexicographical_compare(_X.begin(), _X.end(),
                _Y.begin(), _Y.end())); }
template<class _K, class _Ty, class _Kfn,
        class _Pr, class _A> inline
        bool operator>(const _Tree<_K, _Ty, _Kfn, _Pr, _A>& _X,
                const _Tree<_K, _Ty, _Kfn, _Pr, _A>& _Y)
        {return (_Y < _X); }
template<class _K, class _Ty, class _Kfn,
        class _Pr, class _A> inline
        bool operator<=(const _Tree<_K, _Ty, _Kfn, _Pr, _A>& _X,
                const _Tree<_K, _Ty, _Kfn, _Pr, _A>& _Y)
        {return (!(_Y < _X)); }
template<class _K, class _Ty, class _Kfn,
        class _Pr, class _A> inline
        bool operator>=(const _Tree<_K, _Ty, _Kfn, _Pr, _A>& _X,
                const _Tree<_K, _Ty, _Kfn, _Pr, _A>& _Y)
        {return (!(_X < _Y)); }
_STD_END
#ifdef  _MSC_VER
#pragma pack(pop)
#endif  /* _MSC_VER */

#endif /* _XTREE_ */

/*
 * Copyright (c) 1995 by P.J. Plauger.  ALL RIGHTS RESERVED. 
 * Consult your license regarding permissions and restrictions.
 */

/*
 * This file is derived from software bearing the following
 * restrictions:
 *
 * Copyright (c) 1994
 * Hewlett-Packard Company
 *
 * Permission to use, copy, modify, distribute and sell this
 * software and its documentation for any purpose is hereby
 * granted without fee, provided that the above copyright notice
 * appear in all copies and that both that copyright notice and
 * this permission notice appear in supporting documentation.
 * Hewlett-Packard Company makes no representations about the
 * suitability of this software for any purpose. It is provided
 * "as is" without express or implied warranty.
 */

/*
 * File modified to make it work across DLL calls by Giancarlo Niccolai
 * Parts changed are marked by JC comment.
 *
 * Copyright (C) 2004 Giancarlo Niccolai
 *
 * The changes are distributed under the same statement as above,
 * including, but not limited to, the exclusion of any express or implied
 * warranty 
 */
