#include <set> 
#include <utility> 
#include <iostream> 
#include <algorithm> 
 
using  std:: make_pair ; 
 
template < typename  X, typename  Y, typename  Xless =  std:: less < X> , typename  Yless =  std:: less < Y>> 
class  bimap
{ 
    typedef  std:: pair < X, Y>                              key_type; 
    typedef  std:: pair < X, Y>                              value_type; 
    typedef  typename  std:: set < key_type> :: iterator        iterator; 
    typedef  typename  std:: set < key_type> :: const_iterator  const_iterator; 
 
    struct  Xcomp
    { 
        bool  operator( ) ( X const  & x1, X const  & x2) 
        { 
            return  ! Xless( ) ( x1, x2)  &&  ! Xless( ) ( x2, x1) ; 
        } 
    } ; 
    struct  Ycomp
    { 
        bool  operator( ) ( Y const  & y1, Y const  & y2) 
        { 
            return  ! Yless( ) ( y1, y2)  &&  ! Yless( ) ( y2, y1) ; 
        } 
    } ; 
    struct  Fless 
    {  // prevents lexicographical comparison for std::pair, so that  
        // every .first value is unique as if it was in its own map 
        bool  operator( ) ( key_type const  & lhs, key_type const  & rhs) 
        { 
            return  Xless( ) ( lhs.first , rhs.first ) ; 
        } 
    } ; 
    /// key and value type are interchangeable 
    std:: set < std:: pair < X, Y> , Fless>  _data; 
 
public : 
    std:: pair < iterator, bool >  insert( X const  & x, Y const  & y) 
    { 
        auto  it =  find_right( y) ; 
        if  ( it ==  end( ) )  {  // every .second value is unique 
            return  _data.insert ( make_pair( x, y) ) ; 
        } 
        return  make_pair( it, false ) ; 
    } 
    iterator find_left( X const  & val) 
    { 
        return  _data.find ( make_pair( val,Y( ) ) ) ; 
    } 
    iterator find_right( Y const  & val) 
    { 
        return  std:: find_if ( _data.begin ( ) , _data.end ( ) , 
            [ & val] ( key_type const  & kt) 
        { 
            return  Ycomp( ) ( kt.second , val) ; 
        } ) ; 
    } 
    iterator end( )    {  return  _data.end ( ) ;    } 
    iterator begin( )  {  return  _data.begin ( ) ;  } 
} ; 
 
template < typename  X, typename  Y, typename  In> 
void  PrintBimapInsertion( X const  & x, Y const  & y, In const  & in) 
{ 
    if  ( in.second )  { 
        std:: cout  <<  "Inserted element ("  
            <<  in.first - > first <<  ", "  <<  in.first - > second <<  ")\n " ; 
    } 
    else  { 
        std:: cout  <<  "Could not insert ("  <<  x <<  ", "  <<  y <<  ") because ("  <<  
            in.first - > first <<  ", "  <<  in.first - > second <<  ") already exists\n " ; 
    } 
} 
 
 
int  main( ) 
{ 
    bimap< std:: string , int >  mb; 
    PrintBimapInsertion( "A" , 1 , mb.insert ( "A" , 1 )  ) ; 
    PrintBimapInsertion( "A" , 2 , mb.insert ( "A" , 2 )  ) ; 
    PrintBimapInsertion( "b" , 2 , mb.insert ( "b" , 2 ) ) ; 
    PrintBimapInsertion( "z" , 2 , mb.insert ( "z" , 2 ) ) ; 
 
    auto  it1 =  mb.find_left ( "A" ) ; 
    if  ( it1 ! =  mb.end ( ) )  { 
        std:: cout  <<  std:: endl  <<  it1- > first <<  ", "  <<  it1- > second <<  std:: endl ; 
    } 
 
    auto  it2 =  mb.find_right ( 2 ) ; 
    if  ( it2 ! =  mb.end ( ) )  { 
        std:: cout  <<  std:: endl  <<  it2- > first <<  ", "  <<  it2- > second <<  std:: endl ; 
    } 
 
    return  0 ; 
} 
 
				I2luY2x1ZGUgPHNldD4KI2luY2x1ZGUgPHV0aWxpdHk+CiNpbmNsdWRlIDxpb3N0cmVhbT4KI2luY2x1ZGUgPGFsZ29yaXRobT4KCnVzaW5nIHN0ZDo6bWFrZV9wYWlyOwoKdGVtcGxhdGU8dHlwZW5hbWUgWCwgdHlwZW5hbWUgWSwgdHlwZW5hbWUgWGxlc3MgPSBzdGQ6Omxlc3M8WD4sIHR5cGVuYW1lIFlsZXNzID0gc3RkOjpsZXNzPFk+PgpjbGFzcyBiaW1hcAp7CiAgICB0eXBlZGVmIHN0ZDo6cGFpcjxYLCBZPiAgICAgICAgICAgICAgICAgICAgICAgICAgICAga2V5X3R5cGU7CiAgICB0eXBlZGVmIHN0ZDo6cGFpcjxYLCBZPiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVfdHlwZTsKICAgIHR5cGVkZWYgdHlwZW5hbWUgc3RkOjpzZXQ8a2V5X3R5cGU+OjppdGVyYXRvciAgICAgICBpdGVyYXRvcjsKICAgIHR5cGVkZWYgdHlwZW5hbWUgc3RkOjpzZXQ8a2V5X3R5cGU+Ojpjb25zdF9pdGVyYXRvciBjb25zdF9pdGVyYXRvcjsKCiAgICBzdHJ1Y3QgWGNvbXAKICAgIHsKICAgICAgICBib29sIG9wZXJhdG9yKCkoWCBjb25zdCAmeDEsIFggY29uc3QgJngyKQogICAgICAgIHsKICAgICAgICAgICAgcmV0dXJuICFYbGVzcygpKHgxLCB4MikgJiYgIVhsZXNzKCkoeDIsIHgxKTsKICAgICAgICB9CiAgICB9OwogICAgc3RydWN0IFljb21wCiAgICB7CiAgICAgICAgYm9vbCBvcGVyYXRvcigpKFkgY29uc3QgJnkxLCBZIGNvbnN0ICZ5MikKICAgICAgICB7CiAgICAgICAgICAgIHJldHVybiAhWWxlc3MoKSh5MSwgeTIpICYmICFZbGVzcygpKHkyLCB5MSk7CiAgICAgICAgfQogICAgfTsKICAgIHN0cnVjdCBGbGVzcyAKICAgIHsgLy8gcHJldmVudHMgbGV4aWNvZ3JhcGhpY2FsIGNvbXBhcmlzb24gZm9yIHN0ZDo6cGFpciwgc28gdGhhdCAKICAgICAgICAvLyBldmVyeSAuZmlyc3QgdmFsdWUgaXMgdW5pcXVlIGFzIGlmIGl0IHdhcyBpbiBpdHMgb3duIG1hcAogICAgICAgIGJvb2wgb3BlcmF0b3IoKShrZXlfdHlwZSBjb25zdCAmbGhzLCBrZXlfdHlwZSBjb25zdCAmcmhzKQogICAgICAgIHsKICAgICAgICAgICAgcmV0dXJuIFhsZXNzKCkobGhzLmZpcnN0LCByaHMuZmlyc3QpOwogICAgICAgIH0KICAgIH07CiAgICAvLy8ga2V5IGFuZCB2YWx1ZSB0eXBlIGFyZSBpbnRlcmNoYW5nZWFibGUKICAgIHN0ZDo6c2V0PHN0ZDo6cGFpcjxYLCBZPiwgRmxlc3M+IF9kYXRhOwoKcHVibGljOgogICAgc3RkOjpwYWlyPGl0ZXJhdG9yLCBib29sPiBpbnNlcnQoWCBjb25zdCAmeCwgWSBjb25zdCAmeSkKICAgIHsKICAgICAgICBhdXRvIGl0ID0gZmluZF9yaWdodCh5KTsKICAgICAgICBpZiAoaXQgPT0gZW5kKCkpIHsgLy8gZXZlcnkgLnNlY29uZCB2YWx1ZSBpcyB1bmlxdWUKICAgICAgICAgICAgcmV0dXJuIF9kYXRhLmluc2VydChtYWtlX3BhaXIoeCwgeSkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbWFrZV9wYWlyKGl0LCBmYWxzZSk7CiAgICB9CiAgICBpdGVyYXRvciBmaW5kX2xlZnQoWCBjb25zdCAmdmFsKQogICAgewogICAgICAgIHJldHVybiBfZGF0YS5maW5kKG1ha2VfcGFpcih2YWwsWSgpKSk7CiAgICB9CiAgICBpdGVyYXRvciBmaW5kX3JpZ2h0KFkgY29uc3QgJnZhbCkKICAgIHsKICAgICAgICByZXR1cm4gc3RkOjpmaW5kX2lmKF9kYXRhLmJlZ2luKCksIF9kYXRhLmVuZCgpLCAKICAgICAgICAgICAgWyZ2YWxdKGtleV90eXBlIGNvbnN0ICZrdCkKICAgICAgICB7CiAgICAgICAgICAgIHJldHVybiBZY29tcCgpKGt0LnNlY29uZCwgdmFsKTsKICAgICAgICB9KTsKICAgIH0KICAgIGl0ZXJhdG9yIGVuZCgpICAgeyByZXR1cm4gX2RhdGEuZW5kKCk7ICAgfQogICAgaXRlcmF0b3IgYmVnaW4oKSB7IHJldHVybiBfZGF0YS5iZWdpbigpOyB9Cn07Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBYLCB0eXBlbmFtZSBZLCB0eXBlbmFtZSBJbj4Kdm9pZCBQcmludEJpbWFwSW5zZXJ0aW9uKFggY29uc3QgJngsIFkgY29uc3QgJnksIEluIGNvbnN0ICZpbikKewogICAgaWYgKGluLnNlY29uZCkgewogICAgICAgIHN0ZDo6Y291dCA8PCAiSW5zZXJ0ZWQgZWxlbWVudCAoIiAKICAgICAgICAgICAgPDwgaW4uZmlyc3QtPmZpcnN0IDw8ICIsICIgPDwgaW4uZmlyc3QtPnNlY29uZCA8PCAiKVxuIjsKICAgIH0KICAgIGVsc2UgewogICAgICAgIHN0ZDo6Y291dCA8PCAiQ291bGQgbm90IGluc2VydCAoIiA8PCB4IDw8ICIsICIgPDwgeSA8PCAiKSBiZWNhdXNlICgiIDw8IAogICAgICAgICAgICBpbi5maXJzdC0+Zmlyc3QgPDwgIiwgIiA8PCBpbi5maXJzdC0+c2Vjb25kIDw8ICIpIGFscmVhZHkgZXhpc3RzXG4iOwogICAgfQp9CgoKaW50IG1haW4oKQp7CiAgICBiaW1hcDxzdGQ6OnN0cmluZywgaW50PiBtYjsKICAgIFByaW50QmltYXBJbnNlcnRpb24oIkEiLCAxLCBtYi5pbnNlcnQoIkEiLCAxKSApOwogICAgUHJpbnRCaW1hcEluc2VydGlvbigiQSIsIDIsIG1iLmluc2VydCgiQSIsIDIpICk7CiAgICBQcmludEJpbWFwSW5zZXJ0aW9uKCJiIiwgMiwgbWIuaW5zZXJ0KCJiIiwgMikpOwogICAgUHJpbnRCaW1hcEluc2VydGlvbigieiIsIDIsIG1iLmluc2VydCgieiIsIDIpKTsKCiAgICBhdXRvIGl0MSA9IG1iLmZpbmRfbGVmdCgiQSIpOwogICAgaWYgKGl0MSAhPSBtYi5lbmQoKSkgewogICAgICAgIHN0ZDo6Y291dCA8PCBzdGQ6OmVuZGwgPDwgaXQxLT5maXJzdCA8PCAiLCAiIDw8IGl0MS0+c2Vjb25kIDw8IHN0ZDo6ZW5kbDsKICAgIH0KCiAgICBhdXRvIGl0MiA9IG1iLmZpbmRfcmlnaHQoMik7CiAgICBpZiAoaXQyICE9IG1iLmVuZCgpKSB7CiAgICAgICAgc3RkOjpjb3V0IDw8IHN0ZDo6ZW5kbCA8PCBpdDItPmZpcnN0IDw8ICIsICIgPDwgaXQyLT5zZWNvbmQgPDwgc3RkOjplbmRsOwogICAgfQoKICAgIHJldHVybiAwOwp9