// #define _GLIBCXX_DEBUG #include using namespace std; using uint = unsigned int; #define UNTIE ios_base::sync_with_stdio( false ); cin.tie( nullptr ) #define CIN( LL , A ) LL A; cin >> A #define TYPE_OF( VAR ) remove_const::type >::type #define FOR( VAR , INITIAL , FINAL_PLUS_ONE ) for( TYPE_OF( FINAL_PLUS_ONE ) VAR = INITIAL ; VAR < FINAL_PLUS_ONE ; VAR ++ ) #define FOREQ( VAR , INITIAL , FINAL ) for( TYPE_OF( FINAL ) VAR = INITIAL ; VAR <= FINAL ; VAR ++ ) #define QUIT return 0 #define RETURN( ANSWER ) cout << ( ANSWER ) << "\n"; QUIT #define TMP template #define TYP typename #define INL inline #define RET return #define CST const #define CEX constexpr #define NEX noexcept #define OPR operator #define PUB public #define PRI private #define STT static #define INT_REF CST int #define CST_INT_REF CST int #define CST_UINT_REF CST uint // #define INT_REF int& // #define CST_INT_REF CST int& // #define CST_UINT_REF CST uint& #define ACCESS( P ) ( *P ) TMP using VLArray = list; // 以下、自分のライブラリ(https://github.com/p-adic/cpp)よりソースコードをコピーして編集している。 TMP class LinkedVector; TMP class IToLinkedVector; TMP class CSTIToLinkedVector; TMP class UnionFindForest; TMP class EoLinkedVector { friend class LinkedVector; friend class IToLinkedVector; friend class CSTIToLinkedVector; TMP friend class UnionFindForest; PRI: T m_t; uint m_prev_entry; uint m_next_entry; PRI: INL EoLinkedVector(); INL EoLinkedVector( CST_UINT_REF prev_entry , CST_UINT_REF next_entry ); PUB: // vectorのreserveに必要。 INL EoLinkedVector( EoLinkedVector&& e ); }; TMP INL EoLinkedVector::EoLinkedVector() : m_t() , m_prev_entry( 0 ) , m_next_entry( 0 ) {} TMP INL EoLinkedVector::EoLinkedVector( CST_UINT_REF prev_entry , CST_UINT_REF next_entry ) : m_t() , m_prev_entry( prev_entry ) , m_next_entry( next_entry ) {} TMP INL EoLinkedVector::EoLinkedVector( EoLinkedVector&& e ) : m_t( move( e.m_t ) ) , m_prev_entry( move( e.m_prev_entry ) ) , m_next_entry( move( e.m_next_entry ) ) {} TMP class EoLinkedVector; TMP class CSTIToLinkedVector; TMP class LinkedVector; TMP class IToLinkedVector { friend CSTIToLinkedVector; friend LinkedVector; PRI: LinkedVector* m_p; uint m_i; PUB: INL IToLinkedVector( LinkedVector* CST& p , CST_UINT_REF i ) NEX; INL IToLinkedVector( CST IToLinkedVector& itr ) NEX; INL T& OPR*() CST; INL T* OPR->() CST; IToLinkedVector& OPR=( CST IToLinkedVector& itr ) NEX; INL void OPR++( int ); INL void OPR--( int ); INL CST LinkedVector& GetLinkedVector() CST NEX; INL LinkedVector& RefLinkedVector() NEX; INL CST_UINT_REF GetIndex() CST NEX; INL CST_UINT_REF RefIndex() NEX; }; TMP class CSTIToLinkedVector { friend LinkedVector; PRI: CST LinkedVector* m_p; uint m_i; PUB: INL CSTIToLinkedVector( CST LinkedVector* CST& p , CST_UINT_REF i ) NEX; INL CSTIToLinkedVector( CST CSTIToLinkedVector& itr ) NEX; INL CSTIToLinkedVector( CST IToLinkedVector& itr ) NEX; INL CST T& OPR*() CST; INL CST T* OPR->() CST; CSTIToLinkedVector& OPR=( CST CSTIToLinkedVector& itr ) NEX; CSTIToLinkedVector& OPR=( CST IToLinkedVector& itr ) NEX; INL void OPR++( int ); INL void OPR--( int ); INL CST LinkedVector& GetLinkedVector() CST NEX; INL CST_UINT_REF GetIndex() CST NEX; INL CST_UINT_REF RefIndex() NEX; STT INL bool Equal( CST IToLinkedVector& , CST IToLinkedVector& ) NEX; STT INL bool Equal( CST CSTIToLinkedVector& , CST IToLinkedVector& ) NEX; STT INL bool Equal( CST IToLinkedVector& , CST CSTIToLinkedVector& ) NEX; STT INL bool Equal( CST CSTIToLinkedVector& , CST CSTIToLinkedVector& ) NEX; }; TMP INL bool OPR==( CST IToLinkedVector& , CST IToLinkedVector& ) NEX; TMP INL bool OPR!=( CST IToLinkedVector& , CST IToLinkedVector& ) NEX; TMP INL bool OPR==( CST CSTIToLinkedVector& , CST IToLinkedVector& ) NEX; TMP INL bool OPR!=( CST CSTIToLinkedVector& , CST IToLinkedVector& ) NEX; TMP INL bool OPR==( CST IToLinkedVector& , CST CSTIToLinkedVector& ) NEX; TMP INL bool OPR!=( CST IToLinkedVector& , CST CSTIToLinkedVector& ) NEX; TMP INL bool OPR==( CST CSTIToLinkedVector& , CST CSTIToLinkedVector& ) NEX; TMP INL bool OPR!=( CST CSTIToLinkedVector& , CST CSTIToLinkedVector& ) NEX; // IToLinkedVector TMP INL IToLinkedVector::IToLinkedVector( LinkedVector* CST& p , CST_UINT_REF i ) NEX : m_p( p ) , m_i( i ) {} TMP INL IToLinkedVector::IToLinkedVector( CST IToLinkedVector& itr ) NEX : m_p( itr.m_p ) , m_i( itr.m_i ) {} TMP INL T& IToLinkedVector::OPR*() CST { RET ( *m_p )[m_i]; } TMP INL T* IToLinkedVector::OPR->() CST { RET &( ( *m_p )[m_i] ); } TMP INL IToLinkedVector& IToLinkedVector::OPR=( CST IToLinkedVector& itr ) NEX { m_p = itr.m_p; m_i = itr.m_i; RET *this; } TMP INL void IToLinkedVector::OPR++( int ) { m_i = m_p->m_entry[m_i].m_next_entry; } TMP INL void IToLinkedVector::OPR--( int ) { m_i = m_p->m_entry[m_i].m_prev_entry; } TMP INL CST LinkedVector& IToLinkedVector::GetLinkedVector() CST NEX { RET *m_p; } TMP INL LinkedVector& IToLinkedVector::RefLinkedVector() NEX { RET *m_p; } TMP INL CST_UINT_REF IToLinkedVector::GetIndex() CST NEX { RET m_i; } TMP INL CST_UINT_REF IToLinkedVector::RefIndex() NEX { RET m_i; } // CSTIToLinkedVector TMP INL CSTIToLinkedVector::CSTIToLinkedVector( CST LinkedVector* CST& p , CST_UINT_REF i ) NEX : m_p( p ) , m_i( i ) {} TMP INL CSTIToLinkedVector::CSTIToLinkedVector( CST CSTIToLinkedVector& itr ) NEX : m_p( itr.m_p ) , m_i( itr.m_i ) {} TMP INL CSTIToLinkedVector::CSTIToLinkedVector( CST IToLinkedVector& itr ) NEX : m_p( itr.m_p ) , m_i( itr.m_i ) {} TMP INL CST T& CSTIToLinkedVector::OPR*() CST { RET ( *m_p )[m_i]; } TMP INL CST T* CSTIToLinkedVector::OPR->() CST { RET &( ( *m_p )[m_i] ); } TMP CSTIToLinkedVector& CSTIToLinkedVector::OPR=( CST CSTIToLinkedVector& itr ) NEX { m_p = itr.m_p; m_i = itr.m_i; RET *this; } TMP CSTIToLinkedVector& CSTIToLinkedVector::OPR=( CST IToLinkedVector& itr ) NEX { m_p = itr.m_p; m_i = itr.m_i; RET *this; } TMP INL void CSTIToLinkedVector::OPR++( int ) { m_i = m_p->m_entry[m_i].m_next_entry; } TMP INL void CSTIToLinkedVector::OPR--( int ) { m_i = m_p->m_entry[m_i].m_prev_entry; } TMP INL CST LinkedVector& CSTIToLinkedVector::GetLinkedVector() CST NEX { RET *m_p; } TMP INL CST_UINT_REF CSTIToLinkedVector::GetIndex() CST NEX { RET m_i; } TMP INL CST_UINT_REF CSTIToLinkedVector::RefIndex() NEX { RET m_i; } TMP INL bool CSTIToLinkedVector::Equal( CST IToLinkedVector& itr0 , CST IToLinkedVector& itr1 ) NEX { RET itr0.m_p == itr1.m_p && itr0.m_i == itr1.m_i; } TMP INL bool CSTIToLinkedVector::Equal( CST CSTIToLinkedVector& itr0 , CST IToLinkedVector& itr1 ) NEX { RET itr0.m_p == itr1.m_p && itr0.m_i == itr1.m_i; } TMP INL bool CSTIToLinkedVector::Equal( CST IToLinkedVector& itr0 , CST CSTIToLinkedVector& itr1 ) NEX { RET itr0.m_p == itr1.m_p && itr0.m_i == itr1.m_i; } TMP INL bool CSTIToLinkedVector::Equal( CST CSTIToLinkedVector& itr0 , CST CSTIToLinkedVector& itr1 ) NEX { RET itr0.m_p == itr1.m_p && itr0.m_i == itr1.m_i; } TMP INL bool OPR==( CST IToLinkedVector& itr0 , CST IToLinkedVector& itr1 ) NEX { RET CSTIToLinkedVector::Equal( itr0 , itr1 ); } TMP INL bool OPR!=( CST IToLinkedVector& itr0 , CST IToLinkedVector& itr1 ) NEX { RET !( itr0 == itr1 );} TMP INL bool OPR==( CST CSTIToLinkedVector& itr0 , CST IToLinkedVector& itr1 ) NEX { RET CSTIToLinkedVector::Equal( itr0 , itr1 ); } TMP INL bool OPR!=( CST CSTIToLinkedVector& itr0 , CST IToLinkedVector& itr1 ) NEX { RET !( itr0 == itr1 );} TMP INL bool OPR==( CST IToLinkedVector& itr0 , CST CSTIToLinkedVector& itr1 ) NEX { RET CSTIToLinkedVector::Equal( itr0 , itr1 ); } TMP INL bool OPR!=( CST IToLinkedVector& itr0 , CST CSTIToLinkedVector& itr1 ) NEX { RET !( itr0 == itr1 );} TMP INL bool OPR==( CST CSTIToLinkedVector& itr0 , CST CSTIToLinkedVector& itr1 ) NEX { RET CSTIToLinkedVector::Equal( itr0 , itr1 ); } TMP INL bool OPR!=( CST CSTIToLinkedVector& itr0 , CST CSTIToLinkedVector& itr1 ) NEX { RET !( itr0 == itr1 );} TMP class IToLinkedVector; TMP class CSTIToLinkedVector; TMP class LinkedVector { friend IToLinkedVector; friend CSTIToLinkedVector; protected: vector > m_entry; uint m_front_linked_entry; uint m_back_linked_entry; uint m_size_of_vector; uint m_size_of_link; PUB: INL LinkedVector(); // 要素やそのメンバへのポインタをメンバに持ちうるクラスに対しては // vectorのcapacityを超える際のコピーでポインタの参照先が無効になってしまうので // 予め最大要素数を設定する。 INL LinkedVector( CST_UINT_REF max_size ); // vector上でi番目の要素を返す。 INL CST T& OPR[]( CST_UINT_REF i ) CST; INL T& OPR[]( CST_UINT_REF i ); // link上でi番目の要素の座標を返す。 uint GetLinkedEntry( CST_UINT_REF i ) CST; INL CST_UINT_REF GetFrontLinkedEntryIndex() CST NEX; INL CST_UINT_REF GetBackLinkedEntryIndex() CST NEX; INL CST_UINT_REF GetSizeOfVector() CST NEX; INL CST_UINT_REF GetSizeOfLink() CST NEX; INL bool EmptyVector() CST NEX; INL bool EmptyLink() CST NEX; INL void push_back(); TMP void push_back( CST U& u ); TMP INL void push_back( CST U& u , CST ARGS&... args ); INL void SetPreviousLink( CST_UINT_REF i , CST_UINT_REF j ); INL void SetNexttLink( CST_UINT_REF i , CST_UINT_REF j ); INL CST_UINT_REF GetPreviousLinkIndex( CST_UINT_REF i ) CST; INL CST_UINT_REF GetNexttLinkIndex( CST_UINT_REF i ) CST; // vector上でi番目の要素がlink上にある場合のみサポート CST_UINT_REF DeLink( CST_UINT_REF i ); // vector上でi番目の要素がlink上にない場合のみサポート void ReLink( CST_UINT_REF i ); using iterator = IToLinkedVector; using CST_iterator = CSTIToLinkedVector; // *thisがCSTである場合に確実にCST_iterator返しをするために、iterator返しは非CSTにする必要がある。 INL iterator GetIterator( CST_UINT_REF i ) NEX; INL CST_iterator GetIterator( CST_UINT_REF i ) CST NEX; INL iterator begin() NEX; INL CST_iterator begin() CST NEX; INL iterator end() NEX; INL CST_iterator end() CST NEX; // itrの指す要素がlink上にある場合のみサポート iterator erase( iterator& itr ); protected: INL EoLinkedVector& push_back_Body_0(); INL void push_back_Body_1( EoLinkedVector& e ); }; TMP INL LinkedVector::LinkedVector() : m_entry( 1 ) , m_front_linked_entry( 0 ) , m_back_linked_entry( 0 ) , m_size_of_vector( 0 ) , m_size_of_link( 0 ) {} TMP LinkedVector::LinkedVector( CST_UINT_REF max_size ) : m_entry() , m_front_linked_entry( 0 ) , m_back_linked_entry( 0 ) , m_size_of_vector( 0 ) , m_size_of_link( 0 ) { m_entry.shrink_to_fit(); CST uint capacity = m_entry.capacity(); m_entry.reserve( max_size + 1 ); // 一旦メモリの再確保を生じさせる。 for( uint i = 0 ; i <= capacity ; i++ ){ m_entry.push_back( EoLinkedVector() ); } for( uint i = 0 ; i < capacity ; i++ ){ m_entry.pop_back(); } } TMP INL CST T& LinkedVector::OPR[]( CST_UINT_REF i ) CST { RET m_entry[i].m_t; } TMP INL T& LinkedVector::OPR[]( CST_UINT_REF i ) { RET m_entry[i].m_t; } TMP uint LinkedVector::GetLinkedEntry( CST_UINT_REF i ) CST { uint linked_entry = m_front_linked_entry; for( uint j = 0 ; j < i ; j++ ){ linked_entry = m_entry[linked_entry].m_next_entry; } RET linked_entry; } TMP INL CST_UINT_REF LinkedVector::GetFrontLinkedEntryIndex() CST NEX { RET m_front_linked_entry; } TMP INL CST_UINT_REF LinkedVector::GetBackLinkedEntryIndex() CST NEX { RET m_back_linked_entry; } TMP INL CST_UINT_REF LinkedVector::GetSizeOfVector() CST NEX { RET m_size_of_vector; } TMP INL CST_UINT_REF LinkedVector::GetSizeOfLink() CST NEX { RET m_size_of_link; } TMP INL bool LinkedVector::EmptyVector() CST NEX { RET m_size_of_vector == 0; } TMP INL bool LinkedVector::EmptyLink() CST NEX { RET m_size_of_link == 0; } TMP INL void LinkedVector::push_back() {} TMP TMP void LinkedVector::push_back( CST U& u ) { EoLinkedVector& e = push_back_Body_0(); e.m_t = u; push_back_Body_1( e ); RET; } TMP TMP INL void LinkedVector::push_back( CST U& u , CST ARGS&... args ) { push_back( u ); push_back( args... ); } TMP INL EoLinkedVector& LinkedVector::push_back_Body_0() { m_entry.push_back( EoLinkedVector( m_size_of_vector , m_front_linked_entry ) ); RET m_entry[m_size_of_vector]; } TMP INL void LinkedVector::push_back_Body_1( EoLinkedVector& e ) { e.m_next_entry = m_size_of_vector + 1; m_entry[m_front_linked_entry].m_prev_entry = m_size_of_vector + 1; m_back_linked_entry = m_size_of_vector; m_size_of_vector++; m_size_of_link++; } TMP INL void LinkedVector::SetPreviousLink( CST_UINT_REF i , CST_UINT_REF j ) { m_entry[i].m_prev_entry = j; } TMP INL void LinkedVector::SetNexttLink( CST_UINT_REF i , CST_UINT_REF j ) { m_entry[i].m_next_entry = j; } TMP INL CST_UINT_REF LinkedVector::GetPreviousLinkIndex( CST_UINT_REF i ) CST { RET m_entry[i].m_prev_entry; } TMP INL CST_UINT_REF LinkedVector::GetNexttLinkIndex( CST_UINT_REF i ) CST { RET m_entry[i].m_next_entry; } TMP CST_UINT_REF LinkedVector::DeLink( CST_UINT_REF i ) { CST EoLinkedVector& e = m_entry[i]; m_entry[e.m_prev_entry].m_next_entry = e.m_next_entry; m_entry[e.m_next_entry].m_prev_entry = e.m_prev_entry; if( m_front_linked_entry == i ){ m_front_linked_entry = e.m_next_entry; } if( m_back_linked_entry == i ){ m_back_linked_entry = e.m_prev_entry; } m_size_of_link--; RET e.m_next_entry; } TMP void LinkedVector::ReLink( CST_UINT_REF i ) { EoLinkedVector& current_entry = m_entry[i]; if( m_size_of_link == 0 ){ EoLinkedVector& end_entry = m_entry[m_size_of_vector]; end_entry.m_prev_entry = end_entry.m_next_entry = i; current_entry.m_prev_entry = current_entry.m_next_entry = m_size_of_vector; m_front_linked_entry = m_back_linked_entry = i; } else { uint prev; if( m_front_linked_entry > i ){ m_front_linked_entry = i; prev = m_size_of_vector; } else { prev = m_front_linked_entry; } if( m_back_linked_entry < i ){ m_back_linked_entry = i; } prev = m_entry[prev].m_next_entry; while( prev < i ){ prev = m_entry[prev].m_next_entry; } CST uint next = prev; EoLinkedVector& next_entry = m_entry[next]; prev = next_entry.m_prev_entry; EoLinkedVector& prev_entry = m_entry[prev]; prev_entry.m_next_entry = i; current_entry.m_prev_entry = prev; current_entry.m_next_entry = next; next_entry.m_prev_entry = i; } m_size_of_link++; RET; } TMP INL TYP LinkedVector::iterator LinkedVector::GetIterator( CST_UINT_REF i ) NEX { RET TYP LinkedVector::iterator( this , i ); } TMP INL TYP LinkedVector::CST_iterator LinkedVector::GetIterator( CST_UINT_REF i ) CST NEX { RET TYP LinkedVector::CST_iterator( this , i ); } TMP INL TYP LinkedVector::iterator LinkedVector::begin() NEX { RET TYP LinkedVector::iterator( this , m_front_linked_entry ); } TMP INL TYP LinkedVector::CST_iterator LinkedVector::begin() CST NEX { RET TYP LinkedVector::CST_iterator( this , m_front_linked_entry ); } TMP INL TYP LinkedVector::iterator LinkedVector::end() NEX { RET TYP LinkedVector::iterator( this , m_size_of_vector ); } TMP INL TYP LinkedVector::CST_iterator LinkedVector::end() CST NEX { RET TYP LinkedVector::CST_iterator( this , m_size_of_vector ); } TMP TYP LinkedVector::iterator LinkedVector::erase( TYP LinkedVector::iterator& itr ) { RET TYP LinkedVector::iterator( this , DeLink( itr.m_i ) ); } TMP class IToVLTree; TMP class CSTIToVLTree; TMP class VLSubTree; TMP class EoUnionFindForest; TMP class EoVLTree { friend IToVLTree; friend CSTIToVLTree; friend VLSubTree; friend EoUnionFindForest; PRI: T m_t; EoVLTree* m_left_branch; EoVLTree* m_right_branch; EoVLTree* m_leftmost_node; EoVLTree* m_rightmost_node; PRI: INL EoVLTree(); TMP INL EoVLTree( CST Arg& ); TMP INL EoVLTree( CST Arg& , EoVLTree* CST& , EoVLTree* CST& ); INL EoVLTree( CST EoVLTree& ); EoVLTree& OPR=( CST EoVLTree& ); }; TMP INL EoVLTree::EoVLTree() : m_t() , m_left_branch( this ) , m_right_branch( this ) , m_leftmost_node( this ) , m_rightmost_node( this ) {} TMP TMP INL EoVLTree::EoVLTree( CST Arg& t ) : EoVLTree( t , this , this ) {} TMP TMP INL EoVLTree::EoVLTree( CST Arg& t , EoVLTree* CST& left_branch , EoVLTree* CST& right_branch ) : m_t( t ) , m_left_branch( left_branch ) , m_right_branch( right_branch ) , m_leftmost_node( this ) , m_rightmost_node( this ) {} TMP INL EoVLTree::EoVLTree( CST EoVLTree& e ) : m_t( e.m_t ) , m_left_branch( e.m_left_branch == &e ? this : e.m_left_branch ) , m_right_branch( e.m_right_branch == &e ? this : e.m_right_branch ) , m_leftmost_node( this ) , m_rightmost_node( this ) { if( e.m_leftmost_node != &e ){ m_leftmost_node = e.m_leftmost_node; m_rightmost_node = e.m_rightmost_node; } } TMP EoVLTree& EoVLTree::OPR=( CST EoVLTree& e ) { m_t = e.m_t; m_left_branch = ( e.m_left_branch == &e ? this : e.m_left_branch ); m_right_branch = ( e.m_right_branch == &e ? this : e.m_right_branch ); if( e.m_leftmost_node == &e ){ m_leftmost_node = m_rightmost_node = this; } else { m_leftmost_node = e.m_leftmost_node; m_rightmost_node = e.m_rightmost_node; } RET *this; } TMP class EoVLTree; TMP class CSTIToVLTree; TMP class VLSubTree; TMP class EoVLArray; TMP class IToVLTree { friend CSTIToVLTree; friend VLSubTree; friend EoVLArray >; PRI: EoVLTree* m_p; PRI: // SqIteratorOVLTree経由でのみ呼び出し可能。 INL IToVLTree() NEX; PUB: INL IToVLTree( EoVLTree* CST& ) NEX; INL IToVLTree( CST IToVLTree& ) NEX; INL T& OPR*() CST; INL T* OPR->() CST; IToVLTree& OPR=( CST IToVLTree& ) NEX; // 通常と異なり自身への参照を渡す。 IToVLTree& OPR++( int ) NEX; IToVLTree& OPR--( int ) NEX; // 引数が0の時は何もしない。正の時はm_leftmost_nodeに進んでインクリメント、負の時はm_rightmost_nodeに進んでディクリメント。 IToVLTree& OPR[]( CST_INT_REF ); IToVLTree& Shift() NEX; TMP IToVLTree& Shift( CST_INT_REF , CST Args&... ); INL bool IsLeaf() CST NEX; INL bool IsLeftMost() CST NEX; INL bool IsRightMost() CST NEX; INL bool IsValid() CST NEX; }; TMP class CSTIToVLTree { friend VLSubTree; friend EoVLArray >; PRI: CST EoVLTree* m_p; PRI: // SqCSTIteratorOVLTree経由でのみ呼び出し可能。 INL CSTIToVLTree() NEX; PUB: INL CSTIToVLTree( CST EoVLTree* CST& ) NEX; INL CSTIToVLTree( CST CSTIToVLTree& ) NEX; INL CSTIToVLTree( CST IToVLTree& ) NEX; INL CST T& OPR*() CST; INL CST T* OPR->() CST; CSTIToVLTree& OPR=( CST CSTIToVLTree& ) NEX; CSTIToVLTree& OPR=( CST IToVLTree& ) NEX; // 通常と異なり自身への参照を渡す。 CSTIToVLTree& OPR++( int ) NEX; CSTIToVLTree& OPR--( int ) NEX; // 引数が0の時は何もしない。正の時はm_leftmost_nodeに進んでインクリメント、負の時はm_rightmost_nodeに進んでディクリメント。 CSTIToVLTree& OPR[]( CST_INT_REF ); CSTIToVLTree& Shift() NEX; TMP CSTIToVLTree& Shift( CST_INT_REF , CST Args&... ); INL bool IsLeaf() CST NEX; INL bool IsLeftMost() CST NEX; INL bool IsRightMost() CST NEX; INL bool IsValid() CST NEX; STT INL bool Equal( CST IToVLTree& , CST IToVLTree& ) NEX; STT INL bool Equal( CST CSTIToVLTree& , CST IToVLTree& ) NEX; STT INL bool Equal( CST IToVLTree& , CST CSTIToVLTree& ) NEX; STT INL bool Equal( CST CSTIToVLTree& , CST CSTIToVLTree& ) NEX; }; TMP INL bool OPR==( CST IToVLTree& , CST IToVLTree& ) NEX; TMP INL bool OPR!=( CST IToVLTree& , CST IToVLTree& ) NEX; TMP INL bool OPR==( CST CSTIToVLTree& , CST IToVLTree& ) NEX; TMP INL bool OPR!=( CST CSTIToVLTree& , CST IToVLTree& ) NEX; TMP INL bool OPR==( CST IToVLTree& , CST CSTIToVLTree& ) NEX; TMP INL bool OPR!=( CST IToVLTree& , CST CSTIToVLTree& ) NEX; TMP INL bool OPR==( CST CSTIToVLTree& , CST CSTIToVLTree& ) NEX; TMP INL bool OPR!=( CST CSTIToVLTree& , CST CSTIToVLTree& ) NEX; // IToVLTree TMP INL IToVLTree::IToVLTree() NEX : m_p( nullptr ) {} TMP INL IToVLTree::IToVLTree( EoVLTree* CST& p ) NEX : m_p( p ) {} TMP INL IToVLTree::IToVLTree( CST IToVLTree& itr ) NEX : m_p( itr.m_p ) {} TMP INL T& IToVLTree::OPR*() CST { RET m_p->m_t; } TMP INL T* IToVLTree::OPR->() CST { RET &( *( *this ) ); } TMP IToVLTree& IToVLTree::OPR=( CST IToVLTree& itr ) NEX { m_p = itr.m_p; RET *this; } TMP IToVLTree& IToVLTree::OPR++( int ) NEX { if( m_p == nullptr ){ RET *this; } if( m_p == m_p->m_right_branch ){ m_p = nullptr; } else { m_p = m_p->m_right_branch; } RET *this; } TMP IToVLTree& IToVLTree::OPR--( int ) NEX { if( m_p == nullptr ){ RET *this; } if( m_p == m_p->m_left_branch ){ m_p = nullptr; } else { m_p = m_p->m_left_branch; } RET *this; } TMP IToVLTree& IToVLTree::OPR[]( CST_INT_REF n ) { if( n > 0 ){ m_p = m_p->m_leftmost_node; for( int i = 1 ; i < n ; i++ ){ m_p = m_p->m_right_branch; } } else { if( n < 0 ){ m_p = m_p->m_rightmost_node; for( int i = -1 ; n < i ; i-- ){ m_p = m_p->m_left_branch; } } } RET *this; } TMP IToVLTree& IToVLTree::Shift() NEX { RET *this; } TMP TMP IToVLTree& IToVLTree::Shift( CST_INT_REF n , CST Args&... args ) { OPR[]( n ); RET Shift( args... ); } TMP INL bool IToVLTree::IsLeaf() CST NEX { RET ( m_p == nullptr ) ? false : ( m_p == m_p->m_leftmost_node ); } TMP INL bool IToVLTree::IsLeftMost() CST NEX { RET ( m_p == nullptr ) ? false : ( m_p == m_p->m_left_branch ); } TMP INL bool IToVLTree::IsRightMost() CST NEX { RET ( m_p == nullptr ) ? false : ( m_p == m_p->m_right_branch ); } TMP INL bool IToVLTree::IsValid() CST NEX { RET m_p != nullptr; } // CSTIToVLTree TMP INL CSTIToVLTree::CSTIToVLTree() NEX : m_p( nullptr ) {} TMP INL CSTIToVLTree::CSTIToVLTree( CST EoVLTree* CST& p ) NEX : m_p( p ) {} TMP INL CSTIToVLTree::CSTIToVLTree( CST CSTIToVLTree& itr ) NEX : m_p( itr.m_p ) {} TMP INL CSTIToVLTree::CSTIToVLTree( CST IToVLTree& itr ) NEX : m_p( itr.m_p ) {} TMP INL CST T& CSTIToVLTree::OPR*() CST { RET m_p->m_t; }; TMP INL CST T* CSTIToVLTree::OPR->() CST { RET &( *( *this ) ); } TMP CSTIToVLTree& CSTIToVLTree::OPR=( CST CSTIToVLTree& itr ) NEX { m_p = itr.m_p; RET *this; } TMP CSTIToVLTree& CSTIToVLTree::OPR=( CST IToVLTree& itr ) NEX { m_p = itr.m_p; RET *this; } TMP CSTIToVLTree& CSTIToVLTree::OPR++( int ) NEX { if( m_p == nullptr ){ RET *this; } if( m_p == m_p->m_right_branch ){ m_p = nullptr; } else { m_p = m_p->m_right_branch; } RET *this; } TMP CSTIToVLTree& CSTIToVLTree::OPR--( int ) NEX { if( m_p == nullptr ){ RET *this; } if( m_p == m_p->m_left_branch ){ m_p = nullptr; } else { m_p = m_p->m_left_branch; } RET *this; } TMP CSTIToVLTree& CSTIToVLTree::OPR[]( CST_INT_REF n ) { if( n > 0 ){ m_p = m_p->m_leftmost_node; for( int i = 1 ; i < n ; i++ ){ m_p = m_p->m_right_branch; } } if( n < 0 ){ m_p = m_p->m_rightmost_node; for( int i = -1 ; n < i ; i-- ){ m_p = m_p->m_left_branch; } } RET *this; } TMP CSTIToVLTree& CSTIToVLTree::Shift() NEX { RET *this; } TMP TMP CSTIToVLTree& CSTIToVLTree::Shift( CST_INT_REF n , CST Args&... args ) { OPR[]( n ); RET Shift( args... ); } TMP INL bool CSTIToVLTree::IsLeaf() CST NEX { RET ( m_p == nullptr ) ? false : ( m_p == m_p->m_leftmost_mode ); } TMP INL bool CSTIToVLTree::IsLeftMost() CST NEX { RET ( m_p == nullptr ) ? false : ( m_p == m_p->m_left_branch ); } TMP INL bool CSTIToVLTree::IsRightMost() CST NEX { RET ( m_p == nullptr ) ? false : ( m_p == m_p->m_right_branch ); } TMP INL bool CSTIToVLTree::IsValid() CST NEX { RET m_p != nullptr; } TMP INL bool CSTIToVLTree::Equal( CST IToVLTree& itr0 , CST IToVLTree& itr1 ) NEX { RET itr0.m_p == itr1.m_p; } TMP INL bool CSTIToVLTree::Equal( CST CSTIToVLTree& itr0 , CST IToVLTree& itr1 ) NEX { RET itr0.m_p == itr1.m_p; } TMP INL bool CSTIToVLTree::Equal( CST IToVLTree& itr0 , CST CSTIToVLTree& itr1 ) NEX { RET itr0.m_p == itr1.m_p; } TMP INL bool CSTIToVLTree::Equal( CST CSTIToVLTree& itr0 , CST CSTIToVLTree& itr1 ) NEX { RET itr0.m_p == itr1.m_p; } TMP INL bool OPR==( CST IToVLTree& itr0 , CST IToVLTree& itr1 ) NEX { RET CSTIToVLTree::Equal( itr0 , itr1 ); } TMP INL bool OPR!=( CST IToVLTree& itr0 , CST IToVLTree& itr1 ) NEX { RET !( itr0 == itr1 );} TMP INL bool OPR==( CST CSTIToVLTree& itr0 , CST IToVLTree& itr1 ) NEX { RET CSTIToVLTree::Equal( itr0 , itr1 ); } TMP INL bool OPR!=( CST CSTIToVLTree& itr0 , CST IToVLTree& itr1 ) NEX { RET !( itr0 == itr1 );} TMP INL bool OPR==( CST IToVLTree& itr0 , CST CSTIToVLTree& itr1 ) NEX { RET CSTIToVLTree::Equal( itr0 , itr1 ); } TMP INL bool OPR!=( CST IToVLTree& itr0 , CST CSTIToVLTree& itr1 ) NEX { RET !( itr0 == itr1 );} TMP INL bool OPR==( CST CSTIToVLTree& itr0 , CST CSTIToVLTree& itr1 ) NEX { RET CSTIToVLTree::Equal( itr0 , itr1 ); } TMP INL bool OPR!=( CST CSTIToVLTree& itr0 , CST CSTIToVLTree& itr1 ) NEX { RET !( itr0 == itr1 );} TMP class VLTree; TMP class EoUnionFindForest; TMP class VLSubTree { friend VLTree; friend EoUnionFindForest; friend UnionFindForest; PRI: EoVLTree m_e; // 通常はm_eを指すが、VLSubTree( EoVLTree& )や // VLSubTree( CST IToVLTree& )経由で呼び出された場合のみ // 参照元のNodeを指す。 EoVLTree* m_p_root; uint m_size; PRI: // Tは引数0のコンストラクタを持つクラスのみ許容。 // デストラクタがdelete演算子を呼ばないため、VLTreeかForest経由でしか呼び出してはいけない。 INL VLSubTree(); // Tは引数0のコンストラクタを持つクラスのみ許容。 // rootのみの木に引数たちをpush_RightMostして高々m_size == 1の木を構築する。 // デストラクタがdelete演算子を呼ばないため、VLTree経由でしか呼び出してはいけない。 TMP INL VLSubTree( CST Arg1& , CST Arg2&... ); // Tが引数0のコンストラクタを持たないクラスの場合に使用。 // デストラクタがdelete演算子を呼ばないため、VLTree経由でしか呼び出してはいけない。 // TMP INL VLSubTree( CST WrappedType& t ); // 構築された木への変更がコピー元へは反映されない。 // デストラクタがdelete演算子を呼ばないため、VLTree経由でしか呼び出してはいけない。 // Substriture_Bodyを経由するため、自身への変更が引数へは反映されない。 // 引数をVLSubCSTTreeにしたものを定義して委譲するとループしてしまう。 INL VLSubTree( CST VLSubTree& ); // 構築された木への変更がコピー元へは反映される。 // VLTreeを経由しなくても呼び出して良い。 // VLTreeを経由してはならない。 INL VLSubTree( EoVLTree& ); INL VLSubTree( CST IToVLTree& ); // 構築された木への変更がコピー元へは反映されない。 // デストラクタがdelete演算子を呼ばないため、VLTree経由でしか呼び出してはいけない。 // intはダミー引数。 INL VLSubTree( CST_INT_REF , CST EoVLTree& ); INL VLSubTree( CST_INT_REF , CST CSTIToVLTree& ); // 部分木のコピーを構築してpush_RightMostNodeで挿入するため、自身への変更が引数へは反映されない。 // LeafToTreeとpush_RightMostとConcatenateの相互再帰。 // m_size == 0の時しか呼んではいけない。 void LeafToTree( CST VLSubTree& ); // 新たにRightMostNodeを構築し、そこを部分木のRootとして結合する。 // 構築された木への変更がコピー元へ反映される。 // Forest経由でしか呼び出してはいけない。 void Graft( VLSubTree& ); PUB: virtual ~VLSubTree() = default; // Substriture_Bodyを経由するため、引数が自身と独立でさえあれば、自身への変更が引数へは反映されない。 // CutBranchesを呼び出すため、引数が自身と独立でない場合は、自身への変更が引数へ反映されうる上に、Segmentation Faultを引き起こす可能性がある。 // 引数をVLTreeにしたものを定義して呼び出すとループしてしまう。 VLSubTree& OPR=( CST VLSubTree& ); INL CST_UINT_REF size() CST NEX; INL void CutBranches(); INL bool IsLeaf() CST NEX; // 部分木を構築して返すため、部分木への変更が自身へも反映される。 INL VLSubTree LeftMostSubTree(); INL VLSubTree RightMostSubTree(); // 部分木のコピーを構築して返すため、部分木への変更が自身へは反映されない。 INL VLTree LeftMostSubTreeCopy() CST; INL VLTree RightMostSubTreeCopy() CST; // LeafToTreeとpush_RightMostとConcatenateの相互再帰。 INL void push_RightMost() CST NEX; TMP void push_RightMost( CST Arg1& , CST Arg2&... ); TMP void push_RightMost( CST VLTree& , CST Args&... ); TMP void push_LeftMost( CST Arg& ); void pop_RightMost(); void pop_LeftMost(); // m_size == 1(特にm_p_root->m_leftmost_node== m_p_root->m_rightmost_node)の時しか呼んではならない。 // m_p_rootはdelete可能とは限らないため、代わりに値のすげかえを行い実際にdeleteされるのはm_p_rootでなくm_p_root->m_leftmost_nodeである。 // 従って特にiteratorの処理に注意が必要。 void pop_Root(); using iterator = IToVLTree; using CST_iterator = CSTIToVLTree; // *thisがCSTである場合に確実にCST_iterator返しをするために、iterator返しは非CSTにする必要がある。 INL iterator LeftMostNode() NEX; INL CST_iterator LeftMostNode() CST NEX; INL iterator RightMostNode() NEX; INL CST_iterator RightMostNode() CST NEX; iterator LeftMostLeaf() NEX; CST_iterator LeftMostLeaf() CST NEX; iterator RightMostLeaf() NEX; CST_iterator RightMostLeaf() CST NEX; INL iterator Root() NEX; INL CST_iterator Root() CST NEX; TMP INL iterator GetIterator( CST Args&... ); TMP INL CST_iterator GetIterator( CST Args&... ) CST; // iteratorの右に新たなLeafを構築する。 TMP void insert( CST iterator& , CST Arg& ); // RightMostである場合はrootへのイテレータを返す。 iterator erase( iterator& ); // RootやNodeのラベルに直接読み書きを行う。 INL CST T& GetRoot() CST NEX; INL T& RefRoot() NEX; INL void SetRoot( CST T& ); TMP INL CST T& GetNode( CST Args&... ) CST; // 部分木を構築して返すため、部分木への変更が自身へも反映される。 VLSubTree OPR[]( CST_UINT_REF ); VLSubTree OPR[]( iterator& ); // 部分木のコピーを構築して返すため、部分木への変更が自身へは反映されない。 VLTree OPR[]( CST CST_iterator& ) CST; VLTree GetBranchCopy( CST_UINT_REF ) CST; VLTree GetBranchCopy( CST iterator& ) CST; VLTree GetBranchCopy( CST CST_iterator& ) CST; // 現在のRightMostNodeやiteratorの指す位置を部分木のRootとしてコピーを構築する。 // 構築された木への変更がコピー元へは反映されない。 // LeafToTreeとpush_RightMostとConcatenateの相互再帰。 void Concatenate( CST VLTree& ); void Concatenate( CST iterator& , CST VLTree& ); bool CheckContain( CST iterator& ) CST NEX; bool CheckContain( CST CST_iterator& ) CST NEX; string Display() CST; }; TMP bool OPR==( CST VLTree& , CST VLTree& ); TMP INL bool OPR!=( CST VLTree& , CST VLTree& ); TMP INL VLSubTree::VLSubTree() : m_e() , m_p_root( &m_e ) , m_size( 0 ) {} TMP TMP INL VLSubTree::VLSubTree( CST Arg1& t0 , CST Arg2&... t1 ) : VLSubTree() { push_RightMost( t0 , t1... ); } // TMP TMP INL VLSubTree::VLSubTree( CST WrappedType& t ) : m_e( t.Get() ) , m_p_root( &m_e ) , m_size( 0 ) {} TMP INL VLSubTree::VLSubTree( CST VLSubTree& a ) : m_e( a.m_e.m_t ) , m_p_root( &m_e ) , m_size( 0 ) { LeafToTree( a ); } TMP VLSubTree::VLSubTree( EoVLTree& e ) : m_e( e ) , m_p_root( &e ) , m_size( 0 ) { EoVLTree* p = m_p_root->m_leftmost_node; if( p != m_p_root ){ m_size++; EoVLTree* CST p_rightmost = m_p_root->m_rightmost_node; while( p != p_rightmost ){ p = p->m_right_branch; m_size++; } } } TMP INL VLSubTree::VLSubTree( CST IToVLTree& itr ) : VLSubTree( *( itr.m_p ) ) {} TMP VLSubTree::VLSubTree( CST_INT_REF dummy , CST EoVLTree& e ) : m_e( e.m_t ) , m_p_root( &m_e ) , m_size( 0 ) { CST EoVLTree* p = e.m_leftmost_node; CST EoVLTree* CST p_rightmost = e.m_rightmost_node; bool b = ( p != &e ); while( b ){ push_RightMost( VLTree( dummy , *p ) ); b = ( p != p_rightmost ); p = p->m_right_branch; } } TMP INL VLSubTree::VLSubTree( CST_INT_REF dummy , CST CSTIToVLTree& itr ) : VLSubTree( dummy , *( itr.m_p ) ) {} TMP VLSubTree& VLSubTree::OPR=( CST VLSubTree& a ) { if( this != &a ){ CutBranches(); LeafToTree( a ); } RET *this; } TMP void VLSubTree::LeafToTree( CST VLSubTree& a ) { m_p_root->m_t = a.m_p_root->m_t; EoVLTree* p = a.m_p_root->m_leftmost_node; CST_UINT_REF N = a.m_size; for( uint n = 0 ; n < N ; n++ ){ push_RightMost( VLTree( 0 , *p ) ); p = p->m_right_branch; } RET; } TMP INL CST_UINT_REF VLSubTree::size() CST NEX { RET m_size; } TMP INL void VLSubTree::CutBranches(){ while( m_size > 0 ) pop_RightMost(); } TMP INL bool VLSubTree::IsLeaf() CST NEX { RET m_size == 0; } TMP INL VLSubTree VLSubTree::LeftMostSubTree() { RET VLSubTree( *( m_p_root->m_leftmost_node ) ); } TMP INL VLSubTree VLSubTree::RightMostSubTree() { RET VLSubTree( *( m_p_root->m_rightmost_node ) ); } TMP INL VLTree VLSubTree::LeftMostSubTreeCopy() CST { RET VLTree( 0 , *( m_p_root->m_leftmost_node ) ); } TMP INL VLTree VLSubTree::RightMostSubTreeCopy() CST { RET VLTree( 0 , *( m_p_root->m_rightmost_node ) ); } TMP INL void VLSubTree::push_RightMost() CST NEX {} TMP TMP void VLSubTree::push_RightMost( CST Arg1& t0 , CST Arg2&... t1 ) { auto p = new EoVLTree( t0 ); EoVLTree*& p_rightmost = m_p_root->m_rightmost_node; if( p_rightmost == m_p_root ){ m_p_root->m_leftmost_node = p; } else { p->m_left_branch = p_rightmost; p_rightmost->m_right_branch = p; } p_rightmost = p; m_size++; push_RightMost( t1... ); RET; } TMP TMP void VLSubTree::push_RightMost( CST VLTree& t0 , CST Args&... t1 ) { push_RightMost( t0.m_p_root->m_t ); Concatenate( t0 ); push_RightMost( t1... ); RET; } TMP TMP void VLSubTree::push_LeftMost( CST Arg& t ) { auto p = new EoVLTree( t ); EoVLTree*& p_leftmost = m_p_root->m_leftmost_node; if( p_leftmost == m_p_root ){ m_p_root->m_rightmost_node = p; } else { p->m_right_branch = p_leftmost; p_leftmost->m_left_branch = p; } p_leftmost = p; m_size++; RET; } TMP void VLSubTree::pop_RightMost() { // if( m_size == 0 ){ // ERR_CALL; // } EoVLTree* p_rightmost = m_p_root->m_rightmost_node; VLSubTree t{ *p_rightmost }; t.CutBranches(); if( m_size == 1 ){ m_p_root->m_leftmost_node = m_p_root; m_p_root->m_rightmost_node = m_p_root; } else { EoVLTree* CST& p_rightmost_prev = p_rightmost->m_left_branch; m_p_root->m_rightmost_node = p_rightmost_prev; p_rightmost_prev->m_right_branch = p_rightmost_prev; } delete p_rightmost; m_size--; RET; } TMP void VLSubTree::pop_LeftMost() { // if( m_size == 0 ){ // ERR_CALL; // } EoVLTree* p_leftmost = m_p_root->m_leftmost_node; VLSubTree t{ *p_leftmost }; t.CutBranches(); if( m_size == 1 ){ m_p_root->m_leftmost_node = m_p_root; m_p_root->m_rightmost_node = m_p_root; } else { EoVLTree* CST& p_leftmost_next = p_leftmost->m_right_branch; m_p_root->m_leftmost_node = p_leftmost_next; p_leftmost_next->m_left_branch = p_leftmost_next; } delete p_leftmost; m_size--; RET; } TMP void VLSubTree::pop_Root() { // if( m_size != 1 ){ // ERR_CALL; // } EoVLTree* p_unique_node = m_p_root->m_leftmost_node; m_p_root->m_t = p_unique_node->m_t; m_p_root->m_leftmost_node = p_unique_node->m_leftmost_node; m_p_root->m_rightmost_node = p_unique_node->m_rightmost_node; delete p_unique_node; EoVLTree* p_node = m_p_root->m_leftmost_node; m_size = 0; if( p_node != m_p_root ){ m_size++; while( p_node != p_node->m_right_branch ){ p_node = p_node->m_right_branch; m_size++; } } RET; } TMP INL TYP VLSubTree::iterator VLSubTree::LeftMostNode() NEX { RET IToVLTree( m_p_root->m_leftmost_node ); } TMP INL TYP VLSubTree::CST_iterator VLSubTree::LeftMostNode() CST NEX { RET CSTIToVLTree( m_p_root->m_leftmost_node ); } TMP INL TYP VLSubTree::iterator VLSubTree::RightMostNode() NEX { RET IToVLTree( m_p_root->m_rightmost_node ); } TMP INL TYP VLSubTree::CST_iterator VLSubTree::RightMostNode() CST NEX { RET CSTIToVLTree( m_p_root->m_rightmost_node ); } TMP TYP VLSubTree::iterator VLSubTree::LeftMostLeaf() NEX { EoVLTree* p = m_p_root->m_leftmost_node; while( p != p->m_leftmost_node ){ p = p->m_leftmost_node; } RET IToVLTree( p ); } TMP TYP VLSubTree::CST_iterator VLSubTree::LeftMostLeaf() CST NEX { CST EoVLTree* p = m_p_root->m_leftmost_node; while( p != p->m_leftmost_node ){ p = p->m_leftmost_node; } RET CSTIToVLTree( p ); } TMP TYP VLSubTree::iterator VLSubTree::RightMostLeaf() NEX { EoVLTree* p = m_p_root->m_rightmost_node; while( p != p->m_rightmost_node ){ p = p->m_rightmost_node; } RET IToVLTree( p ); } TMP TYP VLSubTree::CST_iterator VLSubTree::RightMostLeaf() CST NEX { CST EoVLTree* p = m_p_root->m_rightmost_node; while( p != p->m_rightmost_node ){ p = p->m_rightmost_node; } RET CSTIToVLTree( p ); } TMP INL TYP VLSubTree::iterator VLSubTree::Root() NEX { RET IToVLTree( m_p_root ); } TMP INL TYP VLSubTree::CST_iterator VLSubTree::Root() CST NEX { RET CSTIToVLTree( m_p_root ); } TMP TMP INL TYP VLSubTree::iterator VLSubTree::GetIterator( CST Args&... args ) { RET Root().Shift( args... ); } TMP TMP INL TYP VLSubTree::CST_iterator VLSubTree::GetIterator( CST Args&... args ) CST { RET Root().Shift( args... ); } TMP TMP void VLSubTree::insert( CST TYP VLSubTree::iterator& itr , CST Arg& t ) { EoVLTree* CST& p0 = itr.m_p; EoVLTree* CST& p1 = p0->m_right_branch; auto p = new EoVLTree( t , p0 , p1 ); p1->m_left_branch = p; p0->m_right_branch = p; m_size++; RET; } TMP TYP VLSubTree::iterator VLSubTree::erase( TYP VLSubTree::iterator& itr ) { EoVLTree* CST p = itr.m_p; EoVLTree* CST p0 = p->m_left_branch; EoVLTree* CST p1 = p->m_right_branch; if( ! itr.IsLeaf() ){ VLSubTree t_sub{ *p }; t_sub.CutBranches(); } if( p0 != p ){ if( p != p1 ){ itr++; p0->m_right_branch = p1; p1->m_left_branch = p0; } else { itr--; p0->m_right_branch = p0; m_p_root->m_rightmost_node = p0; } } else { if( p != p1 ){ itr++; p1->m_left_branch = p1; m_p_root->m_leftmost_node = p1; } else { itr = Root(); m_p_root->m_leftmost_node = m_p_root; m_p_root->m_rightmost_node = m_p_root; } } delete p; m_size--; RET itr; } TMP INL CST T& VLSubTree::GetRoot() CST NEX { RET m_p_root->m_t; } TMP INL T& VLSubTree::RefRoot() NEX { RET m_p_root->m_t; } TMP INL void VLSubTree::SetRoot( CST T& t ){ m_p_root->m_t = t; } TMP TMP INL CST T& VLSubTree::GetNode( CST Args&... args ) CST { RET ACCESS( GetIterator( args... ) ); } TMP VLSubTree VLSubTree::OPR[]( CST_UINT_REF i ) { if( i <= m_size / 2 ){ EoVLTree* p = m_p_root->m_leftmost_node; for( uint n = 0 ; n < i ; n++ ){ p = p->m_right_branch; } RET VLSubTree( *p ); } EoVLTree* p = m_p_root->m_rightmost_node; for( uint n = m_size - 1 ; n > i ; n-- ){ p = p->m_left_branch; } RET VLSubTree( *p ); } TMP VLSubTree VLSubTree::OPR[]( TYP VLSubTree::iterator& itr ) { RET VLSubTree( *( itr.m_p ) ); } TMP VLTree VLSubTree::OPR[]( CST TYP VLSubTree::CST_iterator& itr ) CST { RET VLTree( 0 , itr.m_p ); } TMP VLTree VLSubTree::GetBranchCopy( CST_UINT_REF i ) CST { if( i <= m_size / 2 ){ CST EoVLTree* p = m_p_root->m_leftmost_node; for( uint n = 0 ; n < i ; n++ ){ p = p->m_right_branch; } RET VLTree( 0 , *p ); } CST EoVLTree* p = m_p_root->m_rightmost_node; for( uint n = m_size - 1 ; n > i ; n-- ){ p = p->m_left_branch; } RET VLTree( 0 , *p ); } TMP VLTree VLSubTree::GetBranchCopy( CST TYP VLSubTree::iterator& itr ) CST { RET VLTree( 0 , *( itr.m_p ) ); } TMP VLTree VLSubTree::GetBranchCopy( CST TYP VLSubTree::CST_iterator& itr ) CST { RET VLTree( 0 , *( itr.m_p ) ); } TMP void VLSubTree::Concatenate( CST VLTree& t ) { EoVLTree* CST p_rightmost = m_p_root->m_rightmost_node; if( m_p_root == p_rightmost ){ LeafToTree( t ); } else { VLSubTree( *p_rightmost ).LeafToTree( t ); } RET; } TMP void VLSubTree::Concatenate( CST TYP VLSubTree::iterator& itr , CST VLTree& t ) { EoVLTree* CST p = itr.m_p; if( m_p_root == p ){ LeafToTree( t ); } else { VLSubTree( *p ).LeafToTree( t ); } RET; } TMP void VLSubTree::Graft( VLSubTree& t ) { EoVLTree*& p_rightmost = m_p_root->m_rightmost_node; if( m_p_root == p_rightmost ){ p_rightmost = m_p_root->m_leftmost_node = t.m_p_root; } else { t.m_p_root->m_left_branch = p_rightmost; p_rightmost = p_rightmost->m_right_branch = t.m_p_root; } RET; } TMP bool VLSubTree::CheckContain( CST iterator& itr ) CST NEX { auto p0 = itr.m_p; auto p1 = m_p_root->m_leftmost_node; for( uint i = 0 ; i < m_size ; i++ ){ if( p0 == p1 ){ RET true; } p1 = p1->m_right_branch; } RET false; } TMP bool VLSubTree::CheckContain( CST CST_iterator& itr ) CST NEX { auto p0 = itr.m_p; auto p1 = m_p_root->m_leftmost_node; for( uint i = 0 ; i < m_size ; i++ ){ if( p0 == p1 ){ RET true; } p1 = p1->m_right_branch; } RET false; } TMP string VLSubTree::Display() CST { string s = to_string( m_p_root->m_t ); s += "("; CST EoVLTree* p = m_p_root->m_leftmost_node; for( uint i = 0 ; i < m_size ; i++ ){ if( i > 0 ){ s += ","; } s += VLTree( 0 , *p ).Display(); p = p->m_right_branch; } s += ")"; RET s; } TMP bool OPR==( CST VLTree& t1 , CST VLTree& t2 ) { if( t1.GetRoot() != t2.GetRoot() ){ RET false; } if( t1.IsLeaf() ){ RET t2.IsLeaf(); } if( t2.IsLeaf() ){ RET false; } auto itr1 = t1.LeftMostNode(); auto itr2 = t2.LeftMostNode(); while( itr1.IsValid() && itr2.IsValid() ){ if( t1.GetBranchCopy( *itr1 ) != t2.GetBranchCopy( *itr2 ) ){ RET false; } itr1++; itr2++; } RET !( itr1.IsValid() || itr2.IsValid() ); } TMP INL bool OPR!=( CST VLTree& t1 , CST VLTree& t2 ) { RET !( t1 == t2 ); } TMP class VLTree : PUB VLSubTree { PUB: TMP INL VLTree( CST Args&... ); VLTree( EoVLTree& ) = delete; virtual ~VLTree(); TMP VLTree& OPR=( CST Arg& ); }; TMP TMP INL VLTree::VLTree( CST Args&... t ) : VLSubTree( t... ) {} TMP VLTree::~VLTree(){ VLSubTree::CutBranches(); } TMP TMP VLTree& VLTree::OPR=( CST Arg& t ) { VLSubTree::OPR=( t ); RET *this; } TMP class UnionFindForest; TMP class EoLinkedVector; TMP class EoUnionFindForest { friend UnionFindForest; friend EoLinkedVector >; PRI: VLSubTree m_node; uint m_pred_node; uint m_root; uint m_depth; PRI: INL EoUnionFindForest(); INL EoUnionFindForest( CST T& t , CST_UINT_REF num ); INL EoUnionFindForest( EoUnionFindForest&& e ); }; TMP INL EoUnionFindForest::EoUnionFindForest() : m_node() , m_pred_node( 0 ) , m_root( 0 ) , m_depth( 0 ) {} TMP INL EoUnionFindForest::EoUnionFindForest( CST T& t , CST_UINT_REF num ) : m_node() , m_pred_node( num ) , m_root( num ) , m_depth( 0 ) { m_node.SetRoot( t ); } TMP INL EoUnionFindForest::EoUnionFindForest( EoUnionFindForest&& e ) : m_node() , m_pred_node( move( e.m_pred_node ) ) , m_root( move( e.m_root ) ) , m_depth( move( e.m_depth ) ) { m_node.SetRoot( move( e.m_node.m_p_root->m_t ) ); } TMP class UnionFindForest : PUB LinkedVector > { PUB: // EoUnionFindForest::m_nodeはVLSubTree型でありポインタをメンバに持つため // 予め最大要素数を固定しないといけない。 INL UnionFindForest( CST_UINT_REF max_size ); // num番目のNodeをRootとする部分木を構築する。 // INL CST VLSubTree& GetSubTree( CST_UINT_REF num ) CST; INL VLSubTree& GetSubTree( CST_UINT_REF num ); // num番目のNodeのPredecessor Nodeを返す。 INL CST_UINT_REF GetPredecessorNode( CST_UINT_REF num ) CST; // num番目のNodeのRootを計算して返す。 CST_UINT_REF GetRootOfNode( CST_UINT_REF num ); // num番目のRootを返す。 uint GetRoot( CST_UINT_REF num ) CST; // num番目のNodeに格納された値への参照を返す。 INL CST T& OPR[]( CST uint& num ) CST; INL T& OPR[]( CST uint& num ); INL CST_UINT_REF GetSizeOfNode() CST NEX; INL CST_UINT_REF GetSizeOfRoot() CST NEX; // 最初に指定したmax_sizeよりGetSizeOfNode()が大きい場合はサポート外 INL void push_RightMost(); void push_RightMost( CST T& t ); TMP INL void push_RightMost( CST T& t , CST ARGS&... args ); INL void push_back() = delete; TMP void push_back( CST U& u ) = delete; TMP INL void push_back( CST U& u , CST ARGS&... args ) = delete; INL void SetPreviousLink( CST_UINT_REF i , CST_UINT_REF j ) = delete; INL void SetNexttLink( CST_UINT_REF i , CST_UINT_REF j ) = delete; INL CST_UINT_REF GetPreviousLinkIndex( CST_UINT_REF i ) CST = delete; INL CST_UINT_REF GetNexttLinkIndex( CST_UINT_REF i ) CST = delete; CST_UINT_REF DeLink( CST_UINT_REF i ) = delete; void ReLink( CST_UINT_REF i ) = delete; void Graft( CST_UINT_REF num0 , CST_UINT_REF num1 ); }; TMP INL UnionFindForest::UnionFindForest( CST_UINT_REF max_size ) : LinkedVector >( max_size ) {} // TMP INL CST VLSubTree& UnionFindForest::GetSubTree( CST_UINT_REF num ) CST { RET LinkedVector >::OPR[]( num ).m_node; } TMP INL VLSubTree& UnionFindForest::GetSubTree( CST_UINT_REF num ) { RET LinkedVector >::OPR[]( num ).m_node; } TMP INL CST_UINT_REF UnionFindForest::GetPredecessorNode( CST_UINT_REF num ) CST { RET LinkedVector >::OPR[]( num ).m_pred_node; } TMP CST_UINT_REF UnionFindForest::GetRootOfNode( CST_UINT_REF num ) { uint& root = LinkedVector >::OPR[]( num ).m_root; if( root != LinkedVector >::OPR[]( root ).m_root ){ root = GetRootOfNode( root ); } RET root; } TMP uint UnionFindForest::GetRoot( CST_UINT_REF num ) CST { auto itr = LinkedVector >::begin(); for( uint i = 0 ; i < num ; i++ ){ itr++; } RET itr.GetIndex(); } TMP INL CST T& UnionFindForest::OPR[]( CST uint& num ) CST { RET LinkedVector >::OPR[]( num ).m_node.GetRoot(); } TMP INL T& UnionFindForest::OPR[]( CST uint& num ) { RET LinkedVector >::OPR[]( num ).m_node.RefRoot(); } TMP INL CST_UINT_REF UnionFindForest::GetSizeOfNode() CST NEX { RET LinkedVector >::GetSizeOfVector(); } TMP INL CST_UINT_REF UnionFindForest::GetSizeOfRoot() CST NEX { RET LinkedVector >::GetSizeOfLink(); } TMP INL void UnionFindForest::push_RightMost() {} TMP void UnionFindForest::push_RightMost( CST T& t ) { EoLinkedVector >& e = LinkedVector >::push_back_Body_0(); e.m_t.m_node.SetRoot( t ); e.m_t.m_pred_node = e.m_t.m_root = LinkedVector >::m_size_of_vector; LinkedVector >::push_back_Body_1( e ); RET; } TMP TMP INL void UnionFindForest::push_RightMost( CST T& t , CST ARGS&... args ) { push_RightMost( t ); push_RightMost( args... ); } TMP void UnionFindForest::Graft( CST_UINT_REF num0 , CST_UINT_REF num1 ) { CST_UINT_REF e0_root_index = LinkedVector >::OPR[]( num0 ).m_root; CST_UINT_REF e1_root_index = LinkedVector >::OPR[]( num1 ).m_root; // if( e0_root_index == e1_root_index ){ // RET; // } EoUnionFindForest& e0_root = LinkedVector >::OPR[]( e0_root_index ); EoUnionFindForest& e1_root = LinkedVector >::OPR[]( e1_root_index ); // CST uint i0 = ( e0_root.m_depth < e1_root.m_depth ? 0 : 1 ); // CST uint i1 = 1 - i0; // EoUnionFindForest* CST p_e_root[2] = { &e0_root , &e1_root }; // EoUnionFindForest& root_0 = *( p_e_root[i0] ); // EoUnionFindForest& root_1 = *( p_e_root[i1] ); // if( root_0.m_depth == root_1.m_depth ){ // root_1.m_depth++; // } // root_1.m_node.Graft( root_0.m_node ); // LinkedVector >::DeLink( root_0.m_root ); // root_0.m_root = root_0.m_pred_node = root_1.m_root; e0_root.m_node.Graft( e1_root.m_node ); LinkedVector >::DeLink( e1_root.m_root ); e1_root.m_root = e1_root.m_pred_node = e0_root.m_root; RET; } TMP class SqCSTIToVLTree; TMP class SqIToVLTree : PUB IToVLTree { // キャスト用のコンストラクタにのみ用いる。 friend SqCSTIToVLTree; PRI: VLArray > m_itr; PUB: INL SqIToVLTree( CST IToVLTree& ); INL SqIToVLTree( CST SqIToVLTree& ); SqIToVLTree& OPR=( CST IToVLTree& ); SqIToVLTree& OPR=( CST SqIToVLTree& ); void OPR[]( CST int& ); // INL T& Access_Body( CST char* CST , CST int& , CST char* CST , CST string& , CST uint& ) CST; INL T& Ref( CST uint& ) CST; INL CST T& Get( CST uint& ) CST; INL void pop_front(); void erase_back( VLSubTree& ); bool CheckContained( CST VLSubTree& ) CST; INL uint size() CST NEX; PRI: STT void erase_back_Body( VLSubTree& , SqIToVLTree& ); STT bool CheckContained_Body( CST VLSubTree& , CST SqIToVLTree& ); }; TMP class SqCSTIToVLTree : PUB CSTIToVLTree { PRI: VLArray > m_itr; PUB: INL SqCSTIToVLTree( CST CSTIToVLTree& ); INL SqCSTIToVLTree( CST SqCSTIToVLTree& ); SqCSTIToVLTree( CST SqIToVLTree& ); SqCSTIToVLTree& OPR=( CST CSTIToVLTree& ); SqCSTIToVLTree& OPR=( CST SqCSTIToVLTree& ); void OPR[]( CST int& ); // INL CST T& Access_Body( CST char* CST , CST int& , CST char* CST , CST string& , CST uint& ) CST; INL CST T& Get( CST uint& ) CST; INL void pop_front(); bool CheckContained( CST VLSubTree& ) CST; INL uint size() CST NEX; PRI: STT bool CheckContained_Body( CST VLSubTree& , CST SqCSTIToVLTree& ); }; // SqIToVLTree TMP INL SqIToVLTree::SqIToVLTree( CST IToVLTree& itr ) : IToVLTree( itr ) , m_itr(){} TMP INL SqIToVLTree::SqIToVLTree( CST SqIToVLTree& itr ) : IToVLTree( itr ) , m_itr( itr.m_itr ){} TMP SqIToVLTree& SqIToVLTree::OPR=( CST IToVLTree& itr ) { IToVLTree::OPR=( itr ); m_itr.clear(); RET *this; } TMP SqIToVLTree& SqIToVLTree::OPR=( CST SqIToVLTree& itr ) { IToVLTree::OPR=( itr ); m_itr = itr.m_itr; RET *this; } TMP void SqIToVLTree::OPR[]( CST int& i ) { if( i == 0 ){ IToVLTree::OPR=( m_itr.back() ); m_itr.pop_back(); } else { m_itr.push_back( *this ); IToVLTree::OPR[]( i ); } RET; } TMP INL T& SqIToVLTree::Ref( CST uint& i ) CST { RET i == m_itr.size() ? IToVLTree::OPR*() : *( m_itr[i] ); } TMP INL CST T& SqIToVLTree::Get( CST uint& i ) CST { RET i == m_itr.size() ? IToVLTree::OPR*() : *( m_itr[i] ); } TMP INL void SqIToVLTree::pop_front(){ m_itr.pop_front(); } TMP void SqIToVLTree::erase_back( VLSubTree& t ) { SqIToVLTree itr_copy = *this; if( IToVLTree::IsRightMost() ){ if( IToVLTree::IsLeftMost() ){ OPR[]( 0 ); } else { IToVLTree::OPR--( 0 ); } } else { IToVLTree::OPR++( 0 ); } erase_back_Body( t , itr_copy ); RET; } TMP void SqIToVLTree::erase_back_Body( VLSubTree& t , SqIToVLTree& itr ) { CST uint& L = itr.size(); if( L == 2 ){ t.erase( itr ); } else { itr.pop_front(); VLSubTree t_sub = t[ ( itr.m_itr ).front() ]; erase_back_Body( t_sub , itr ); } RET; } TMP bool SqIToVLTree::CheckContained( CST VLSubTree& t ) CST { if( m_itr.empty() ){ RET true; } SqIToVLTree itr_copy = *this; itr_copy.pop_front(); RET CheckContained_Body( t , itr_copy ); } TMP bool SqIToVLTree::CheckContained_Body( CST VLSubTree& t , CST SqIToVLTree& itr ) { if( ( itr.m_itr ).empty() ){ RET t.CheckContain( itr ); } CST IToVLTree& itr_front = ( itr.m_itr ).front(); if( t.CheckContain( itr_front ) ){ CST VLSubTree t_sub{ itr_front }; SqIToVLTree itr_copy = itr; itr_copy.pop_front(); RET CheckContained_Body( t_sub , itr_copy ); } RET false; } TMP INL uint SqIToVLTree::size() CST NEX { RET m_itr.size() + 1; } // SqCSTIToVLTree TMP INL SqCSTIToVLTree::SqCSTIToVLTree( CST CSTIToVLTree& itr ) : CSTIToVLTree( itr ) , m_itr(){} TMP INL SqCSTIToVLTree::SqCSTIToVLTree( CST SqCSTIToVLTree& itr ) : CSTIToVLTree( itr ) , m_itr( itr.m_itr ){} TMP SqCSTIToVLTree::SqCSTIToVLTree( CST SqIToVLTree& itr ) : CSTIToVLTree( itr ) , m_itr() { for( auto itr_itr = ( itr.m_itr ).begin() , itr_itr_e = ( itr.m_itr ).end() ; itr_itr != itr_itr_e ; itr_itr++ ){ m_itr.push_back( *itr_itr ); } } TMP SqCSTIToVLTree& SqCSTIToVLTree::OPR=( CST CSTIToVLTree& itr ) { CSTIToVLTree::OPR=( itr ); m_itr.clear(); RET *this; } TMP SqCSTIToVLTree& SqCSTIToVLTree::OPR=( CST SqCSTIToVLTree& itr ) { CSTIToVLTree::OPR=( itr ); m_itr = itr.m_itr; RET *this; } TMP void SqCSTIToVLTree::OPR[]( CST int& i ) { if( i == 0 ){ if( ! m_itr.empty() ){ CSTIToVLTree::OPR=( m_itr.back() ); m_itr.pop_back(); } } else { m_itr.push_back( *this ); CSTIToVLTree::OPR[]( i ); } RET; } TMP INL CST T& SqCSTIToVLTree::Get( CST uint& i ) CST { RET i == m_itr.size() ? CSTIToVLTree::OPR*() : *( m_itr[i] ); } TMP INL void SqCSTIToVLTree::pop_front(){ m_itr.pop_front(); } TMP bool SqCSTIToVLTree::CheckContained( CST VLSubTree& t ) CST { if( m_itr.empty() ){ RET true; } SqCSTIToVLTree itr_copy = *this; itr_copy.pop_front(); RET CheckContained_Body( t , itr_copy ); } TMP bool SqCSTIToVLTree::CheckContained_Body( CST VLSubTree& t , CST SqCSTIToVLTree& itr ) { if( ( itr.m_itr ).empty() ){ RET t.CheckContain( itr ); } CST CSTIToVLTree& itr_front = ( itr.m_itr ).front(); if( t.CheckContain( itr_front ) ){ CST VLSubTree t_sub{ IToVLTree( const_cast*>( itr_front.m_p ) ) }; SqCSTIToVLTree itr_copy = itr; itr_copy.pop_front(); RET CheckContained_Body( t_sub , itr_copy ); } RET false; } TMP INL uint SqCSTIToVLTree::size() CST NEX { RET m_itr.size() + 1; } INL CEX CST int length = 1001; INL CEX CST int PLUS = -1; INL CEX CST int MULT = -2; void SetSyntax( CST string& expr , CST uint& i_init , UnionFindForest >& syntax , uint ( &symbol_to_node )[length] ) { uint size = expr.size(); uint layer = 0; uint layer_max = 0; uint operator_layer_min = size; uint operator_location; string operator_symbol; string c; FOR( i , 0 , size ){ c = expr.substr( i , 1 ); if( c == "(" ){ layer++; if( layer_max < layer ){ layer_max = layer; } } else if( c == ")" ){ layer--; } else if( c == "$" || c == "&" ){ if( operator_layer_min > layer ){ operator_layer_min = layer; operator_location = i; operator_symbol = c; } else if( operator_layer_min == layer ){ if( operator_symbol == "&" || c == "$" ){ operator_location = i; operator_symbol = c; } } } } if( operator_layer_min < size ){ c = expr.substr( operator_location , 1 ); uint node0 = syntax.GetSizeOfNode(); symbol_to_node[ operator_location + i_init ] = node0; vector v{}; v.push_back( node0 ); v.push_back( c == "$" ? PLUS : MULT ); v.push_back( 0 ); syntax.push_RightMost( v ); SetSyntax( expr.substr( 0 , operator_location ) , i_init , syntax , symbol_to_node ); syntax.Graft( node0 , node0 + 1 ); uint node1 = syntax.GetSizeOfNode(); SetSyntax( expr.substr( operator_location + 1 ) , operator_location + 1 + i_init , syntax , symbol_to_node ); syntax.Graft( node0 , node1 ); } else { vector v{}; v.push_back( 0 ); v.push_back( 0 ); v.push_back( 0 ); v.push_back( stoi( expr.substr( layer_max , size - layer_max ) ) ); syntax.push_RightMost( v ); } RET; } int main() { UNTIE; CEX CST int bound = 301; CIN( int , M ); assert( 1 <= M && M < bound ); CIN( int , ans ); assert( 0 <= ans && ans < bound ); CIN( string , expr ); uint expr_size = expr.size(); assert( 1 <= expr_size && expr_size < length ); UnionFindForest > syntax{ expr_size }; uint symbol_to_node[length]; SetSyntax( expr , 0 , syntax , symbol_to_node ); if( syntax.GetSizeOfNode() == 1 ){ if( syntax[0].back() == ans ){ RETURN( expr ); } else { RETURN( -1 ); } } SqIToVLTree > itr{ syntax.GetSubTree( syntax.GetRoot( 0 ) ).Root() }; int value; bool passed = false; uint left_size; uint right_size; int left_i; int right_j; CEX CST uint start_num = 3; while( itr.size() != 1 || ! passed ){ if( passed ){ if( itr.IsRightMost() ){ CST vector& right = *itr; itr[0]; itr[1]; CST vector& left = *itr; itr[0]; bool used[301] = {}; left_size = left.size(); right_size = right.size(); if( ( *itr )[1] == PLUS ){ FOR( i , start_num , left_size ){ left_i = left[i]; FOR( j , start_num , right_size ){ right_j = right[j]; value = left_i + right_j; if( value <= M ){ used[value] = true; } value = left_i - right_j; if( 0 <= value ){ used[value] = true; } } } } else { FOR( i , start_num , left_size ){ left_i = left[i]; FOR( j , start_num , right_size ){ right_j = right[j]; value = left_i * right_j; if( value <= M ){ used[value] = true; } if( right_j != 0 ){ value = left_i / right_j; used[value] = true; } } } } vector& centre = *itr; centre.pop_back(); FOREQ( i , 0 , M ){ if( used[i] ){ centre.push_back( i ); } } if( centre.size() == start_num ){ RETURN( -1 ); } } else { itr++; } } else { itr->push_back( 0 ); itr[1]; } passed = ( itr->size() != start_num ); } vector& answers = *itr; bool found = false; uint centre_size = answers.size(); FOR( i , start_num , centre_size ){ if( answers[i] == ans ){ found = true; break; } } if( ! found ){ RETURN( -1 ); } CEX CST uint node_num = 0; CEX CST uint operator_num = 1; CEX CST uint value_num = 2; uint answers_size = answers.size(); while( answers_size > value_num ){ answers.pop_back(); answers_size--; } answers.push_back( ans ); passed = false; int node_to_symbol[length]; while( itr.size() != 1 || ! passed ){ if( itr.IsLeaf() || passed ){ if( itr.IsRightMost() ){ itr[0]; } else { itr++; } } else { vector& centre = *itr; value = centre[value_num]; itr[1]; vector& left = *itr; left_size = left.size(); itr++; vector& right = *itr; right_size = right.size(); itr--; found = false; if( centre[operator_num] == PLUS ){ FOR( i , start_num , left_size ){ left_i = left[i]; FOR( j , start_num , right_size ){ right_j = right[j]; if( value == left_i + right_j ){ found = true; node_to_symbol[centre[node_num]] = 0; } else if( value == left_i - right_j ){ found = true; node_to_symbol[centre[node_num]] = 1; } if( found ){ left[value_num] = left_i; right[value_num] = right_j; break; } } if( found ){ break; } } } else { FOR( i , start_num , left_size ){ left_i = left[i]; FOR( j , start_num , right_size ){ right_j = right[j]; if( value == left_i * right_j ){ found = true; node_to_symbol[centre[node_num]] = 0; } else if( right_j != 0 ? value == left_i / right_j : false ){ found = true; node_to_symbol[centre[node_num]] = 1; } if( found ){ left[value_num] = left_i; right[value_num] = right_j; break; } } if( found ){ break; } } } centre_size = centre.size(); while( centre_size > start_num ){ centre.pop_back(); centre_size--; } } passed = ( itr->size() == start_num ); } string c; FOR( i , 0 , expr_size ){ c = expr.substr( i , 1 ); if( c == "$" ){ if( node_to_symbol[symbol_to_node[i]] == 0 ){ cout << "+"; } else { cout << "-"; } } else if( c == "&" ){ if( node_to_symbol[symbol_to_node[i]] == 0 ){ cout << "*"; } else { cout << "/"; } } else { cout << c; } } RETURN( "" ); }