// #define _GLIBCXX_DEBUG #include using namespace std; using uint = unsigned int; using ll = long long; #define CIN( LL , A ) LL A; cin >> A #define GETLINE( A ) string A; getline( cin , A ) #define GETLINE_SEPARATE( A , SEPARATOR ) string A; getline( cin , A , SEPARATOR ) #define UNTIE ios_base::sync_with_stdio( false ); cin.tie( nullptr ) #define FOR( VAR , INITIAL , FINAL_PLUS_ONE ) for( decltype( FINAL_PLUS_ONE ) VAR = INITIAL ; VAR < FINAL_PLUS_ONE ; VAR ++ ) #define FOREQ( VAR , INITIAL , FINAL ) for( decltype( FINAL ) VAR = INITIAL ; VAR <= FINAL ; VAR ++ ) #define FOR_ITR( ARRAY , ITR , END ) for( auto ITR = ARRAY .begin() , END = ARRAY .end() ; ITR != END ; ITR ++ ) #define REPEAT( HOW_MANY_TIMES ) FOR( VARIABLE_FOR_REPEAT , 0 , HOW_MANY_TIMES ) #define QUIT return 0 #define RETURN( ANSWER ) cout << ( ANSWER ) << "\n"; QUIT #define DOUBLE( PRECISION , ANSWER ) cout << fixed << setprecision( PRECISION ) << ( ANSWER ) << "\n"; QUIT #define MIN( A , B ) A < B ? A : B; #define MAX( A , B ) A < B ? B : A; #define TMP template #define TYP typename #define INL inline #define RET return #define CST const #define NEX noexcept #define OPR operator #define PUB public #define PRI private TMP INL T Absolute( CST T& a ){ RET a > 0 ? a : - a; } #define INT_REF CST int #define CONST_INT_REF CST int #define CONST_UINT_REF CST uint // #define INT_REF int& // #define CONST_INT_REF CST int& // #define CONST_UINT_REF CST uint& // 以下、自分のライブラリ(https://github.com/p-adic/cpp)よりソースコードをコピーして編集している。 TMP class LinkedVector; TMP class IteratorOfLinkedVector; TMP class ConstIteratorOfLinkedVector; TMP class UnionFindForest; TMP class EntryOfLinkedVector { friend class LinkedVector; friend class IteratorOfLinkedVector; friend class ConstIteratorOfLinkedVector; TMP friend class UnionFindForest; PRI: T m_t; uint m_prev_entry; uint m_next_entry; PRI: INL EntryOfLinkedVector(); INL EntryOfLinkedVector( CONST_UINT_REF prev_entry , CONST_UINT_REF next_entry ); PUB: // vectorのreserveに必要。 INL EntryOfLinkedVector( EntryOfLinkedVector&& e ); }; TMP INL EntryOfLinkedVector::EntryOfLinkedVector() : m_t() , m_prev_entry( 0 ) , m_next_entry( 0 ) {} TMP INL EntryOfLinkedVector::EntryOfLinkedVector( CONST_UINT_REF prev_entry , CONST_UINT_REF next_entry ) : m_t() , m_prev_entry( prev_entry ) , m_next_entry( next_entry ) {} TMP INL EntryOfLinkedVector::EntryOfLinkedVector( EntryOfLinkedVector&& 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 EntryOfLinkedVector; TMP class ConstIteratorOfLinkedVector; TMP class LinkedVector; TMP class IteratorOfLinkedVector { friend ConstIteratorOfLinkedVector; friend LinkedVector; PRI: LinkedVector* m_p; uint m_i; PUB: INL IteratorOfLinkedVector( LinkedVector* const& p , CONST_UINT_REF i ) NEX; INL IteratorOfLinkedVector( CST IteratorOfLinkedVector& itr ) NEX; INL T& OPR*() CST; INL T* OPR->() CST; IteratorOfLinkedVector& OPR=( CST IteratorOfLinkedVector& itr ) NEX; INL void OPR++( int ); INL void OPR--( int ); INL CST LinkedVector& GetLinkedVector() CST NEX; INL LinkedVector& RefLinkedVector() NEX; INL CONST_UINT_REF GetIndex() CST NEX; INL CONST_UINT_REF RefIndex() NEX; }; TMP class ConstIteratorOfLinkedVector { friend LinkedVector; PRI: CST LinkedVector* m_p; uint m_i; PUB: INL ConstIteratorOfLinkedVector( CST LinkedVector* const& p , CONST_UINT_REF i ) NEX; INL ConstIteratorOfLinkedVector( CST ConstIteratorOfLinkedVector& itr ) NEX; INL ConstIteratorOfLinkedVector( CST IteratorOfLinkedVector& itr ) NEX; INL CST T& OPR*() CST; INL CST T* OPR->() CST; ConstIteratorOfLinkedVector& OPR=( CST ConstIteratorOfLinkedVector& itr ) NEX; ConstIteratorOfLinkedVector& OPR=( CST IteratorOfLinkedVector& itr ) NEX; INL void OPR++( int ); INL void OPR--( int ); INL CST LinkedVector& GetLinkedVector() CST NEX; INL CONST_UINT_REF GetIndex() CST NEX; INL CONST_UINT_REF RefIndex() NEX; static INL bool Equal( CST IteratorOfLinkedVector& , CST IteratorOfLinkedVector& ) NEX; static INL bool Equal( CST ConstIteratorOfLinkedVector& , CST IteratorOfLinkedVector& ) NEX; static INL bool Equal( CST IteratorOfLinkedVector& , CST ConstIteratorOfLinkedVector& ) NEX; static INL bool Equal( CST ConstIteratorOfLinkedVector& , CST ConstIteratorOfLinkedVector& ) NEX; }; TMP INL bool OPR==( CST IteratorOfLinkedVector& , CST IteratorOfLinkedVector& ) NEX; TMP INL bool OPR!=( CST IteratorOfLinkedVector& , CST IteratorOfLinkedVector& ) NEX; TMP INL bool OPR==( CST ConstIteratorOfLinkedVector& , CST IteratorOfLinkedVector& ) NEX; TMP INL bool OPR!=( CST ConstIteratorOfLinkedVector& , CST IteratorOfLinkedVector& ) NEX; TMP INL bool OPR==( CST IteratorOfLinkedVector& , CST ConstIteratorOfLinkedVector& ) NEX; TMP INL bool OPR!=( CST IteratorOfLinkedVector& , CST ConstIteratorOfLinkedVector& ) NEX; TMP INL bool OPR==( CST ConstIteratorOfLinkedVector& , CST ConstIteratorOfLinkedVector& ) NEX; TMP INL bool OPR!=( CST ConstIteratorOfLinkedVector& , CST ConstIteratorOfLinkedVector& ) NEX; // IteratorOfLinkedVector TMP INL IteratorOfLinkedVector::IteratorOfLinkedVector( LinkedVector* const& p , CONST_UINT_REF i ) NEX : m_p( p ) , m_i( i ) {} TMP INL IteratorOfLinkedVector::IteratorOfLinkedVector( CST IteratorOfLinkedVector& itr ) NEX : m_p( itr.m_p ) , m_i( itr.m_i ) {} TMP INL T& IteratorOfLinkedVector::OPR*() CST { RET ( *m_p )[m_i]; } TMP INL T* IteratorOfLinkedVector::OPR->() CST { RET &( ( *m_p )[m_i] ); } TMP INL IteratorOfLinkedVector& IteratorOfLinkedVector::OPR=( CST IteratorOfLinkedVector& itr ) NEX { m_p = itr.m_p; m_i = itr.m_i; RET *this; } TMP INL void IteratorOfLinkedVector::OPR++( int ) { m_i = m_p->m_entry[m_i].m_next_entry; } TMP INL void IteratorOfLinkedVector::OPR--( int ) { m_i = m_p->m_entry[m_i].m_prev_entry; } TMP INL CST LinkedVector& IteratorOfLinkedVector::GetLinkedVector() CST NEX { RET *m_p; } TMP INL LinkedVector& IteratorOfLinkedVector::RefLinkedVector() NEX { RET *m_p; } TMP INL CONST_UINT_REF IteratorOfLinkedVector::GetIndex() CST NEX { RET m_i; } TMP INL CONST_UINT_REF IteratorOfLinkedVector::RefIndex() NEX { RET m_i; } // ConstIteratorOfLinkedVector TMP INL ConstIteratorOfLinkedVector::ConstIteratorOfLinkedVector( CST LinkedVector* const& p , CONST_UINT_REF i ) NEX : m_p( p ) , m_i( i ) {} TMP INL ConstIteratorOfLinkedVector::ConstIteratorOfLinkedVector( CST ConstIteratorOfLinkedVector& itr ) NEX : m_p( itr.m_p ) , m_i( itr.m_i ) {} TMP INL ConstIteratorOfLinkedVector::ConstIteratorOfLinkedVector( CST IteratorOfLinkedVector& itr ) NEX : m_p( itr.m_p ) , m_i( itr.m_i ) {} TMP INL CST T& ConstIteratorOfLinkedVector::OPR*() CST { RET ( *m_p )[m_i]; } TMP INL CST T* ConstIteratorOfLinkedVector::OPR->() CST { RET &( ( *m_p )[m_i] ); } TMP ConstIteratorOfLinkedVector& ConstIteratorOfLinkedVector::OPR=( CST ConstIteratorOfLinkedVector& itr ) NEX { m_p = itr.m_p; m_i = itr.m_i; RET *this; } TMP ConstIteratorOfLinkedVector& ConstIteratorOfLinkedVector::OPR=( CST IteratorOfLinkedVector& itr ) NEX { m_p = itr.m_p; m_i = itr.m_i; RET *this; } TMP INL void ConstIteratorOfLinkedVector::OPR++( int ) { m_i = m_p->m_entry[m_i].m_next_entry; } TMP INL void ConstIteratorOfLinkedVector::OPR--( int ) { m_i = m_p->m_entry[m_i].m_prev_entry; } TMP INL CST LinkedVector& ConstIteratorOfLinkedVector::GetLinkedVector() CST NEX { RET *m_p; } TMP INL CONST_UINT_REF ConstIteratorOfLinkedVector::GetIndex() CST NEX { RET m_i; } TMP INL CONST_UINT_REF ConstIteratorOfLinkedVector::RefIndex() NEX { RET m_i; } TMP INL bool ConstIteratorOfLinkedVector::Equal( CST IteratorOfLinkedVector& itr0 , CST IteratorOfLinkedVector& itr1 ) NEX { RET itr0.m_p == itr1.m_p && itr0.m_i == itr1.m_i; } TMP INL bool ConstIteratorOfLinkedVector::Equal( CST ConstIteratorOfLinkedVector& itr0 , CST IteratorOfLinkedVector& itr1 ) NEX { RET itr0.m_p == itr1.m_p && itr0.m_i == itr1.m_i; } TMP INL bool ConstIteratorOfLinkedVector::Equal( CST IteratorOfLinkedVector& itr0 , CST ConstIteratorOfLinkedVector& itr1 ) NEX { RET itr0.m_p == itr1.m_p && itr0.m_i == itr1.m_i; } TMP INL bool ConstIteratorOfLinkedVector::Equal( CST ConstIteratorOfLinkedVector& itr0 , CST ConstIteratorOfLinkedVector& itr1 ) NEX { RET itr0.m_p == itr1.m_p && itr0.m_i == itr1.m_i; } TMP INL bool OPR==( CST IteratorOfLinkedVector& itr0 , CST IteratorOfLinkedVector& itr1 ) NEX { RET ConstIteratorOfLinkedVector::Equal( itr0 , itr1 ); } TMP INL bool OPR!=( CST IteratorOfLinkedVector& itr0 , CST IteratorOfLinkedVector& itr1 ) NEX { RET !( itr0 == itr1 );} TMP INL bool OPR==( CST ConstIteratorOfLinkedVector& itr0 , CST IteratorOfLinkedVector& itr1 ) NEX { RET ConstIteratorOfLinkedVector::Equal( itr0 , itr1 ); } TMP INL bool OPR!=( CST ConstIteratorOfLinkedVector& itr0 , CST IteratorOfLinkedVector& itr1 ) NEX { RET !( itr0 == itr1 );} TMP INL bool OPR==( CST IteratorOfLinkedVector& itr0 , CST ConstIteratorOfLinkedVector& itr1 ) NEX { RET ConstIteratorOfLinkedVector::Equal( itr0 , itr1 ); } TMP INL bool OPR!=( CST IteratorOfLinkedVector& itr0 , CST ConstIteratorOfLinkedVector& itr1 ) NEX { RET !( itr0 == itr1 );} TMP INL bool OPR==( CST ConstIteratorOfLinkedVector& itr0 , CST ConstIteratorOfLinkedVector& itr1 ) NEX { RET ConstIteratorOfLinkedVector::Equal( itr0 , itr1 ); } TMP INL bool OPR!=( CST ConstIteratorOfLinkedVector& itr0 , CST ConstIteratorOfLinkedVector& itr1 ) NEX { RET !( itr0 == itr1 );} TMP class IteratorOfLinkedVector; TMP class ConstIteratorOfLinkedVector; TMP class LinkedVector { friend IteratorOfLinkedVector; friend ConstIteratorOfLinkedVector; 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( CONST_UINT_REF max_size ); // vector上でi番目の要素を返す。 INL CST T& OPR[]( CONST_UINT_REF i ) CST; INL T& OPR[]( CONST_UINT_REF i ); // link上でi番目の要素の座標を返す。 uint GetLinkedEntry( CONST_UINT_REF i ) CST; INL CONST_UINT_REF GetFrontLinkedEntryIndex() CST NEX; INL CONST_UINT_REF GetBackLinkedEntryIndex() CST NEX; INL CONST_UINT_REF GetSizeOfVector() CST NEX; INL CONST_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( CONST_UINT_REF i , CONST_UINT_REF j ); INL void SetNexttLink( CONST_UINT_REF i , CONST_UINT_REF j ); INL CONST_UINT_REF GetPreviousLinkIndex( CONST_UINT_REF i ) CST; INL CONST_UINT_REF GetNexttLinkIndex( CONST_UINT_REF i ) CST; // vector上でi番目の要素がlink上にある場合のみサポート CONST_UINT_REF DeLink( CONST_UINT_REF i ); // vector上でi番目の要素がlink上にない場合のみサポート void ReLink( CONST_UINT_REF i ); using iterator = IteratorOfLinkedVector; using const_iterator = ConstIteratorOfLinkedVector; // *thisがconstである場合に確実にconst_iterator返しをするために、iterator返しは非constにする必要がある。 INL iterator GetIterator( CONST_UINT_REF i ) NEX; INL const_iterator GetIterator( CONST_UINT_REF i ) CST NEX; INL iterator begin() NEX; INL const_iterator begin() CST NEX; INL iterator end() NEX; INL const_iterator end() CST NEX; // itrの指す要素がlink上にある場合のみサポート iterator erase( iterator& itr ); protected: INL EntryOfLinkedVector& push_back_Body_0(); INL void push_back_Body_1( EntryOfLinkedVector& 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( CONST_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 ); // 一旦メモリの再確保を生じさせる。 for( uint i = 0 ; i <= capacity ; i++ ){ m_entry.push_back( EntryOfLinkedVector() ); } for( uint i = 0 ; i < capacity ; i++ ){ m_entry.pop_back(); } } TMP INL CST T& LinkedVector::OPR[]( CONST_UINT_REF i ) CST { RET m_entry[i].m_t; } TMP INL T& LinkedVector::OPR[]( CONST_UINT_REF i ) { RET m_entry[i].m_t; } TMP uint LinkedVector::GetLinkedEntry( CONST_UINT_REF i ) const { 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 CONST_UINT_REF LinkedVector::GetFrontLinkedEntryIndex() CST NEX { RET m_front_linked_entry; } TMP INL CONST_UINT_REF LinkedVector::GetBackLinkedEntryIndex() CST NEX { RET m_back_linked_entry; } TMP INL CONST_UINT_REF LinkedVector::GetSizeOfVector() CST NEX { RET m_size_of_vector; } TMP INL CONST_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 ) { EntryOfLinkedVector& 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 EntryOfLinkedVector& LinkedVector::push_back_Body_0() { m_entry.push_back( EntryOfLinkedVector( m_size_of_vector , m_front_linked_entry ) ); RET m_entry[m_size_of_vector]; } TMP INL void LinkedVector::push_back_Body_1( EntryOfLinkedVector& 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( CONST_UINT_REF i , CONST_UINT_REF j ) { m_entry[i].m_prev_entry = j; } TMP INL void LinkedVector::SetNexttLink( CONST_UINT_REF i , CONST_UINT_REF j ) { m_entry[i].m_next_entry = j; } TMP INL CONST_UINT_REF LinkedVector::GetPreviousLinkIndex( CONST_UINT_REF i ) CST { RET m_entry[i].m_prev_entry; } TMP INL CONST_UINT_REF LinkedVector::GetNexttLinkIndex( CONST_UINT_REF i ) CST { RET m_entry[i].m_next_entry; } TMP CONST_UINT_REF LinkedVector::DeLink( CONST_UINT_REF i ) { CST EntryOfLinkedVector& 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( CONST_UINT_REF i ) { EntryOfLinkedVector& current_entry = m_entry[i]; if( m_size_of_link == 0 ){ EntryOfLinkedVector& 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; EntryOfLinkedVector& next_entry = m_entry[next]; prev = next_entry.m_prev_entry; EntryOfLinkedVector& 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( CONST_UINT_REF i ) NEX { RET TYP LinkedVector::iterator( this , i ); } TMP INL TYP LinkedVector::const_iterator LinkedVector::GetIterator( CONST_UINT_REF i ) CST NEX { RET TYP LinkedVector::const_iterator( this , i ); } TMP INL TYP LinkedVector::iterator LinkedVector::begin() NEX { RET TYP LinkedVector::iterator( this , m_front_linked_entry ); } TMP INL TYP LinkedVector::const_iterator LinkedVector::begin() CST NEX { RET TYP LinkedVector::const_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::const_iterator LinkedVector::end() CST NEX { RET TYP LinkedVector::const_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 IteratorOfVLTree; TMP class ConstIteratorOfVLTree; TMP class VLSubTree; TMP class EntryOfUnionFindForest; TMP class EntryOfVLTree { friend IteratorOfVLTree; friend ConstIteratorOfVLTree; friend VLSubTree; friend EntryOfUnionFindForest; PRI: T m_t; EntryOfVLTree* m_left_branch; EntryOfVLTree* m_right_branch; EntryOfVLTree* m_leftmost_node; EntryOfVLTree* m_rightmost_node; PRI: INL EntryOfVLTree(); TMP INL EntryOfVLTree( CST Arg& ); TMP INL EntryOfVLTree( CST Arg& , EntryOfVLTree* const& , EntryOfVLTree* const& ); INL EntryOfVLTree( CST EntryOfVLTree& ); EntryOfVLTree& OPR=( CST EntryOfVLTree& ); }; TMP INL EntryOfVLTree::EntryOfVLTree() : m_t() , m_left_branch( this ) , m_right_branch( this ) , m_leftmost_node( this ) , m_rightmost_node( this ) {} TMP TMP INL EntryOfVLTree::EntryOfVLTree( CST Arg& t ) : EntryOfVLTree( t , this , this ) {} TMP TMP INL EntryOfVLTree::EntryOfVLTree( CST Arg& t , EntryOfVLTree* const& left_branch , EntryOfVLTree* const& 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 EntryOfVLTree::EntryOfVLTree( CST EntryOfVLTree& 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 EntryOfVLTree& EntryOfVLTree::OPR=( CST EntryOfVLTree& 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 EntryOfVLTree; TMP class ConstIteratorOfVLTree; TMP class VLSubTree; TMP class EntryOfVLArray; TMP class IteratorOfVLTree { friend ConstIteratorOfVLTree; friend VLSubTree; friend EntryOfVLArray >; PRI: EntryOfVLTree* m_p; PRI: // SequentialIteratorOVLTree経由でのみ呼び出し可能。 INL IteratorOfVLTree() NEX; PUB: INL IteratorOfVLTree( EntryOfVLTree* const& ) NEX; INL IteratorOfVLTree( CST IteratorOfVLTree& ) NEX; // 非メンバ関数のAccess用 // INL T& Access_Body( CST char* CST , CONST_INT_REF , CST char* CST , CST string& ) CST; INL T& OPR*() CST; INL T* OPR->() CST; IteratorOfVLTree& OPR=( CST IteratorOfVLTree& ) NEX; // 通常と異なり自身への参照を渡す。 IteratorOfVLTree& OPR++( int ) NEX; IteratorOfVLTree& OPR--( int ) NEX; // 引数が0の時は何もしない。正の時はm_leftmost_nodeに進んでインクリメント、負の時はm_rightmost_nodeに進んでディクリメント。 IteratorOfVLTree& OPR[]( CONST_INT_REF ); IteratorOfVLTree& Shift() NEX; TMP IteratorOfVLTree& Shift( CONST_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 ConstIteratorOfVLTree { friend VLSubTree; friend EntryOfVLArray >; PRI: CST EntryOfVLTree* m_p; PRI: // SequentialConstIteratorOVLTree経由でのみ呼び出し可能。 INL ConstIteratorOfVLTree() NEX; PUB: INL ConstIteratorOfVLTree( CST EntryOfVLTree* const& ) NEX; INL ConstIteratorOfVLTree( CST ConstIteratorOfVLTree& ) NEX; INL ConstIteratorOfVLTree( CST IteratorOfVLTree& ) NEX; // 非メンバ関数のAccess用 // INL CST T& Access_Body( CST char* CST , CONST_INT_REF , CST char* CST , CST string& ) CST; INL CST T& OPR*() CST; INL CST T* OPR->() CST; ConstIteratorOfVLTree& OPR=( CST ConstIteratorOfVLTree& ) NEX; ConstIteratorOfVLTree& OPR=( CST IteratorOfVLTree& ) NEX; // 通常と異なり自身への参照を渡す。 ConstIteratorOfVLTree& OPR++( int ) NEX; ConstIteratorOfVLTree& OPR--( int ) NEX; // 引数が0の時は何もしない。正の時はm_leftmost_nodeに進んでインクリメント、負の時はm_rightmost_nodeに進んでディクリメント。 ConstIteratorOfVLTree& OPR[]( CONST_INT_REF ); ConstIteratorOfVLTree& Shift() NEX; TMP ConstIteratorOfVLTree& Shift( CONST_INT_REF , CST Args&... ); INL bool IsLeaf() CST NEX; INL bool IsLeftMost() CST NEX; INL bool IsRightMost() CST NEX; INL bool IsValid() CST NEX; static INL bool Equal( CST IteratorOfVLTree& , CST IteratorOfVLTree& ) NEX; static INL bool Equal( CST ConstIteratorOfVLTree& , CST IteratorOfVLTree& ) NEX; static INL bool Equal( CST IteratorOfVLTree& , CST ConstIteratorOfVLTree& ) NEX; static INL bool Equal( CST ConstIteratorOfVLTree& , CST ConstIteratorOfVLTree& ) NEX; }; TMP INL bool OPR==( CST IteratorOfVLTree& , CST IteratorOfVLTree& ) NEX; TMP INL bool OPR!=( CST IteratorOfVLTree& , CST IteratorOfVLTree& ) NEX; TMP INL bool OPR==( CST ConstIteratorOfVLTree& , CST IteratorOfVLTree& ) NEX; TMP INL bool OPR!=( CST ConstIteratorOfVLTree& , CST IteratorOfVLTree& ) NEX; TMP INL bool OPR==( CST IteratorOfVLTree& , CST ConstIteratorOfVLTree& ) NEX; TMP INL bool OPR!=( CST IteratorOfVLTree& , CST ConstIteratorOfVLTree& ) NEX; TMP INL bool OPR==( CST ConstIteratorOfVLTree& , CST ConstIteratorOfVLTree& ) NEX; TMP INL bool OPR!=( CST ConstIteratorOfVLTree& , CST ConstIteratorOfVLTree& ) NEX; // IteratorOfVLTree TMP INL IteratorOfVLTree::IteratorOfVLTree() NEX : m_p( nullptr ) {} TMP INL IteratorOfVLTree::IteratorOfVLTree( EntryOfVLTree* const& p ) NEX : m_p( p ) {} TMP INL IteratorOfVLTree::IteratorOfVLTree( CST IteratorOfVLTree& itr ) NEX : m_p( itr.m_p ) {} TMP INL T& IteratorOfVLTree::OPR*() CST { RET ( *m_p ).m_t; } TMP INL T* IteratorOfVLTree::OPR->() CST { RET &( *( *this ) ); } TMP IteratorOfVLTree& IteratorOfVLTree::OPR=( CST IteratorOfVLTree& itr ) NEX { m_p = itr.m_p; RET *this; } TMP IteratorOfVLTree& IteratorOfVLTree::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 IteratorOfVLTree& IteratorOfVLTree::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 IteratorOfVLTree& IteratorOfVLTree::OPR[]( CONST_INT_REF n ) { if( n > 0 ){ m_p = ACCESS( m_p ).m_leftmost_node; for( int i = 1 ; i < n ; i++ ){ m_p = ACCESS( m_p ).m_right_branch; } } else { if( n < 0 ){ m_p = ACCESS( m_p ).m_rightmost_node; for( int i = -1 ; n < i ; i-- ){ m_p = ACCESS( m_p ).m_left_branch; } } } RET *this; } TMP IteratorOfVLTree& IteratorOfVLTree::Shift() NEX { RET *this; } TMP TMP IteratorOfVLTree& IteratorOfVLTree::Shift( CONST_INT_REF n , CST Args&... args ) { OPR[]( n ); RET Shift( args... ); } TMP INL bool IteratorOfVLTree::IsLeaf() CST NEX { RET ( m_p == nullptr ) ? false : ( m_p == ( *m_p ).m_leftmost_node ); } TMP INL bool IteratorOfVLTree::IsLeftMost() CST NEX { RET ( m_p == nullptr ) ? false : ( m_p == ( *m_p ).m_left_branch ); } TMP INL bool IteratorOfVLTree::IsRightMost() CST NEX { RET ( m_p == nullptr ) ? false : ( m_p == ( *m_p ).m_right_branch ); } TMP INL bool IteratorOfVLTree::IsValid() CST NEX { RET m_p != nullptr; } // ConstIteratorOfVLTree TMP INL ConstIteratorOfVLTree::ConstIteratorOfVLTree() NEX : m_p( nullptr ) {} TMP INL ConstIteratorOfVLTree::ConstIteratorOfVLTree( CST EntryOfVLTree* const& p ) NEX : m_p( p ) {} TMP INL ConstIteratorOfVLTree::ConstIteratorOfVLTree( CST ConstIteratorOfVLTree& itr ) NEX : m_p( itr.m_p ) {} TMP INL ConstIteratorOfVLTree::ConstIteratorOfVLTree( CST IteratorOfVLTree& itr ) NEX : m_p( itr.m_p ) {} TMP INL CST T& ConstIteratorOfVLTree::OPR*() CST { RET ( *m_p ).m_t; }; TMP INL CST T* ConstIteratorOfVLTree::OPR->() CST { RET &( *( *this ) ); } TMP ConstIteratorOfVLTree& ConstIteratorOfVLTree::OPR=( CST ConstIteratorOfVLTree& itr ) NEX { m_p = itr.m_p; RET *this; } TMP ConstIteratorOfVLTree& ConstIteratorOfVLTree::OPR=( CST IteratorOfVLTree& itr ) NEX { m_p = itr.m_p; RET *this; } TMP ConstIteratorOfVLTree& ConstIteratorOfVLTree::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 ConstIteratorOfVLTree& ConstIteratorOfVLTree::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 ConstIteratorOfVLTree& ConstIteratorOfVLTree::OPR[]( CONST_INT_REF n ) { if( n > 0 ){ m_p = ACCESS( m_p ).m_leftmost_node; for( int i = 1 ; i < n ; i++ ){ m_p = ACCESS( m_p ).m_right_branch; } } if( n < 0 ){ m_p = ACCESS( m_p ).m_rightmost_node; for( int i = -1 ; n < i ; i-- ){ m_p = ACCESS( m_p ).m_left_branch; } } RET *this; } TMP ConstIteratorOfVLTree& ConstIteratorOfVLTree::Shift() NEX { RET *this; } TMP TMP ConstIteratorOfVLTree& ConstIteratorOfVLTree::Shift( CONST_INT_REF n , CST Args&... args ) { OPR[]( n ); RET Shift( args... ); } TMP INL bool ConstIteratorOfVLTree::IsLeaf() CST NEX { RET ( m_p == nullptr ) ? false : ( m_p == ( *m_p ).m_leftmost_mode ); } TMP INL bool ConstIteratorOfVLTree::IsLeftMost() CST NEX { RET ( m_p == nullptr ) ? false : ( m_p == ( *m_p ).m_left_branch ); } TMP INL bool ConstIteratorOfVLTree::IsRightMost() CST NEX { RET ( m_p == nullptr ) ? false : ( m_p == ( *m_p ).m_right_branch ); } TMP INL bool ConstIteratorOfVLTree::IsValid() CST NEX { RET m_p != nullptr; } TMP INL bool ConstIteratorOfVLTree::Equal( CST IteratorOfVLTree& itr0 , CST IteratorOfVLTree& itr1 ) NEX { RET itr0.m_p == itr1.m_p; } TMP INL bool ConstIteratorOfVLTree::Equal( CST ConstIteratorOfVLTree& itr0 , CST IteratorOfVLTree& itr1 ) NEX { RET itr0.m_p == itr1.m_p; } TMP INL bool ConstIteratorOfVLTree::Equal( CST IteratorOfVLTree& itr0 , CST ConstIteratorOfVLTree& itr1 ) NEX { RET itr0.m_p == itr1.m_p; } TMP INL bool ConstIteratorOfVLTree::Equal( CST ConstIteratorOfVLTree& itr0 , CST ConstIteratorOfVLTree& itr1 ) NEX { RET itr0.m_p == itr1.m_p; } TMP INL bool OPR==( CST IteratorOfVLTree& itr0 , CST IteratorOfVLTree& itr1 ) NEX { RET ConstIteratorOfVLTree::Equal( itr0 , itr1 ); } TMP INL bool OPR!=( CST IteratorOfVLTree& itr0 , CST IteratorOfVLTree& itr1 ) NEX { RET !( itr0 == itr1 );} TMP INL bool OPR==( CST ConstIteratorOfVLTree& itr0 , CST IteratorOfVLTree& itr1 ) NEX { RET ConstIteratorOfVLTree::Equal( itr0 , itr1 ); } TMP INL bool OPR!=( CST ConstIteratorOfVLTree& itr0 , CST IteratorOfVLTree& itr1 ) NEX { RET !( itr0 == itr1 );} TMP INL bool OPR==( CST IteratorOfVLTree& itr0 , CST ConstIteratorOfVLTree& itr1 ) NEX { RET ConstIteratorOfVLTree::Equal( itr0 , itr1 ); } TMP INL bool OPR!=( CST IteratorOfVLTree& itr0 , CST ConstIteratorOfVLTree& itr1 ) NEX { RET !( itr0 == itr1 );} TMP INL bool OPR==( CST ConstIteratorOfVLTree& itr0 , CST ConstIteratorOfVLTree& itr1 ) NEX { RET ConstIteratorOfVLTree::Equal( itr0 , itr1 ); } TMP INL bool OPR!=( CST ConstIteratorOfVLTree& itr0 , CST ConstIteratorOfVLTree& itr1 ) NEX { RET !( itr0 == itr1 );} TMP class VLTree; TMP class EntryOfUnionFindForest; TMP class VLSubTree { friend VLTree; friend EntryOfUnionFindForest; friend UnionFindForest; PRI: EntryOfVLTree m_e; // 通常はm_eを指すが、VLSubTree( EntryOfVLTree& )や // VLSubTree( CST IteratorOfVLTree& )経由で呼び出された場合のみ // 参照元のNodeを指す。 EntryOfVLTree* 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を経由するため、自身への変更が引数へは反映されない。 // 引数をVLSubConstTreeにしたものを定義して委譲するとループしてしまう。 INL VLSubTree( CST VLSubTree& ); // 構築された木への変更がコピー元へは反映される。 // VLTreeを経由しなくても呼び出して良い。 // VLTreeを経由してはならない。 INL VLSubTree( EntryOfVLTree& ); INL VLSubTree( CST IteratorOfVLTree& ); // 構築された木への変更がコピー元へは反映されない。 // デストラクタがdelete演算子を呼ばないため、VLTree経由でしか呼び出してはいけない。 // intはダミー引数。 INL VLSubTree( CONST_INT_REF , CST EntryOfVLTree& ); INL VLSubTree( CONST_INT_REF , CST ConstIteratorOfVLTree& ); // 部分木のコピーを構築して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 CONST_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 = IteratorOfVLTree; using const_iterator = ConstIteratorOfVLTree; // *thisがconstである場合に確実にconst_iterator返しをするために、iterator返しは非constにする必要がある。 INL iterator LeftMostNode() NEX; INL const_iterator LeftMostNode() CST NEX; INL iterator RightMostNode() NEX; INL const_iterator RightMostNode() CST NEX; iterator LeftMostLeaf() NEX; const_iterator LeftMostLeaf() CST NEX; iterator RightMostLeaf() NEX; const_iterator RightMostLeaf() CST NEX; INL iterator Root() NEX; INL const_iterator Root() CST NEX; TMP INL iterator GetIterator( CST Args&... ); TMP INL const_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[]( CONST_UINT_REF ); VLSubTree OPR[]( iterator& ); // 部分木のコピーを構築して返すため、部分木への変更が自身へは反映されない。 VLTree OPR[]( CST const_iterator& ) CST; VLTree GetBranchCopy( CONST_UINT_REF ) CST; VLTree GetBranchCopy( CST iterator& ) CST; VLTree GetBranchCopy( CST const_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 const_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( EntryOfVLTree& e ) : m_e( e ) , m_p_root( &e ) , m_size( 0 ) { EntryOfVLTree* p = m_p_root->m_leftmost_node; if( p != m_p_root ){ m_size++; EntryOfVLTree* 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 IteratorOfVLTree& itr ) : VLSubTree( *( itr.m_p ) ) {} TMP VLSubTree::VLSubTree( CONST_INT_REF dummy , CST EntryOfVLTree& e ) : m_e( e.m_t ) , m_p_root( &m_e ) , m_size( 0 ) { CST EntryOfVLTree* p = e.m_leftmost_node; CST EntryOfVLTree* 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( CONST_INT_REF dummy , CST ConstIteratorOfVLTree& 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; EntryOfVLTree* p = a.m_p_root->m_leftmost_node; CONST_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 CONST_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 EntryOfVLTree( t0 ); EntryOfVLTree*& 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 EntryOfVLTree( t ); EntryOfVLTree*& 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; // } EntryOfVLTree* 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 { EntryOfVLTree* const& 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; // } EntryOfVLTree* 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 { EntryOfVLTree* const& 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; // } EntryOfVLTree* 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; EntryOfVLTree* 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 IteratorOfVLTree( m_p_root->m_leftmost_node ); } TMP INL TYP VLSubTree::const_iterator VLSubTree::LeftMostNode() CST NEX { RET ConstIteratorOfVLTree( m_p_root->m_leftmost_node ); } TMP INL TYP VLSubTree::iterator VLSubTree::RightMostNode() NEX { RET IteratorOfVLTree( m_p_root->m_rightmost_node ); } TMP INL TYP VLSubTree::const_iterator VLSubTree::RightMostNode() CST NEX { RET ConstIteratorOfVLTree( m_p_root->m_rightmost_node ); } TMP TYP VLSubTree::iterator VLSubTree::LeftMostLeaf() NEX { EntryOfVLTree* p = m_p_root->m_leftmost_node; while( p != p->m_leftmost_node ){ p = p->m_leftmost_node; } RET IteratorOfVLTree( p ); } TMP TYP VLSubTree::const_iterator VLSubTree::LeftMostLeaf() CST NEX { CST EntryOfVLTree* p = m_p_root->m_leftmost_node; while( p != p->m_leftmost_node ){ p = p->m_leftmost_node; } RET ConstIteratorOfVLTree( p ); } TMP TYP VLSubTree::iterator VLSubTree::RightMostLeaf() NEX { EntryOfVLTree* p = m_p_root->m_rightmost_node; while( p != p->m_rightmost_node ){ p = p->m_rightmost_node; } RET IteratorOfVLTree( p ); } TMP TYP VLSubTree::const_iterator VLSubTree::RightMostLeaf() CST NEX { CST EntryOfVLTree* p = m_p_root->m_rightmost_node; while( p != p->m_rightmost_node ){ p = p->m_rightmost_node; } RET ConstIteratorOfVLTree( p ); } TMP INL TYP VLSubTree::iterator VLSubTree::Root() NEX { RET IteratorOfVLTree( m_p_root ); } TMP INL TYP VLSubTree::const_iterator VLSubTree::Root() CST NEX { RET ConstIteratorOfVLTree( m_p_root ); } TMP TMP INL TYP VLSubTree::iterator VLSubTree::GetIterator( CST Args&... args ) { RET Root().Shift( args... ); } TMP TMP INL TYP VLSubTree::const_iterator VLSubTree::GetIterator( CST Args&... args ) CST { RET Root().Shift( args... ); } TMP TMP void VLSubTree::insert( CST TYP VLSubTree::iterator& itr , CST Arg& t ) { // if( ! CheckContain( itr ) ){ // ERR_IMPUT( itr , t ); // } EntryOfVLTree* const& p0 = itr.m_p; EntryOfVLTree* const& p1 = p0->m_right_branch; auto p = new EntryOfVLTree( 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 ) { // if( ! CheckContain( itr ) ){ // ERR_IMPUT( itr ); // } EntryOfVLTree* CST p = itr.m_p; EntryOfVLTree* CST p0 = p->m_left_branch; EntryOfVLTree* 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[]( CONST_UINT_REF i ) { // if( i >= m_size ){ // ERR_IMPUT( i ); // } if( i <= m_size / 2 ){ EntryOfVLTree* p = m_p_root->m_leftmost_node; for( uint n = 0 ; n < i ; n++ ){ p = p->m_right_branch; } RET VLSubTree( *p ); } EntryOfVLTree* 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 ) { // if( ! CheckContain( itr )){ // ERR_IMPUT( itr ); // } RET VLSubTree( *( itr.m_p ) ); } TMP VLTree VLSubTree::OPR[]( CST TYP VLSubTree::const_iterator& itr ) const { // if( ! CheckContain( itr )){ // ERR_IMPUT( itr ); // } RET VLTree( 0 , itr.m_p ); } TMP VLTree VLSubTree::GetBranchCopy( CONST_UINT_REF i ) const { // if( i >= m_size ){ // ERR_IMPUT( i ); // } if( i <= m_size / 2 ){ CST EntryOfVLTree* p = m_p_root->m_leftmost_node; for( uint n = 0 ; n < i ; n++ ){ p = p->m_right_branch; } RET VLTree( 0 , *p ); } CST EntryOfVLTree* 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 ) const { // if( ! CheckContain( itr ) ){ // ERR_IMPUT( itr ); // } RET VLTree( 0 , *( itr.m_p ) ); } TMP VLTree VLSubTree::GetBranchCopy( CST TYP VLSubTree::const_iterator& itr ) const { // if( ! CheckContain( itr ) ){ // ERR_IMPUT( itr ); // } RET VLTree( 0 , *( itr.m_p ) ); } TMP void VLSubTree::Concatenate( CST VLTree& t ) { EntryOfVLTree* CST p_rightmost = m_p_root->m_rightmost_node; // if( p_rightmost->m_rightmost_node != p_rightmost ){ // ERR_IMPUT( *this , t ); // } 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 ) { // if( ! itr.IsLeaf() ){ // ERR_IMPUT( itr , t ); // } EntryOfVLTree* CST p = itr.m_p; if( m_p_root == p ){ LeafToTree( t ); } else { VLSubTree( *p ).LeafToTree( t ); } RET; } TMP void VLSubTree::Graft( VLSubTree& t ) { EntryOfVLTree*& p_rightmost = m_p_root->m_rightmost_node; // if( p_rightmost->m_rightmost_node != p_rightmost ){ // ERR_IMPUT( *this , t ); // } if( m_p_root == p_rightmost ){ p_rightmost = m_p_root->m_leftmost_node = t.m_p_root; } else { 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 const_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() const { string s = to_string( m_p_root->m_t ); s += "("; CST EntryOfVLTree* 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( EntryOfVLTree& ) = 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 EntryOfLinkedVector; TMP class EntryOfUnionFindForest { friend UnionFindForest; friend EntryOfLinkedVector >; PRI: VLSubTree m_node; uint m_pred_node; uint m_root; uint m_depth; PRI: INL EntryOfUnionFindForest(); INL EntryOfUnionFindForest( CST T& t , CONST_UINT_REF num ); INL EntryOfUnionFindForest( EntryOfUnionFindForest&& e ); }; TMP INL EntryOfUnionFindForest::EntryOfUnionFindForest() : m_node() , m_pred_node( 0 ) , m_root( 0 ) , m_depth( 0 ) {} TMP INL EntryOfUnionFindForest::EntryOfUnionFindForest( CST T& t , CONST_UINT_REF num ) : m_node() , m_pred_node( num ) , m_root( num ) , m_depth( 0 ) { m_node.SetRoot( t ); } TMP INL EntryOfUnionFindForest::EntryOfUnionFindForest( EntryOfUnionFindForest&& 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: // EntryOfUnionFindForest::m_nodeはVLSubTree型でありポインタをメンバに持つため // 予め最大要素数を固定しないといけない。 INL UnionFindForest( CONST_UINT_REF max_size ); // num番目のNodeをRootとする部分木を構築する。 INL CST VLSubTree& GetSubTree( CONST_UINT_REF num ) CST; // num番目のNodeのPredecessor Nodeを返す。 INL CONST_UINT_REF GetPredecessorNode( CONST_UINT_REF num ) CST; // num番目のNodeのRootを計算して返す。 CONST_UINT_REF GetRootOfNode( CONST_UINT_REF num ); // num番目のRootを返す。 uint GetRoot( CONST_UINT_REF num ) CST; // num番目のNodeに格納された値への参照を返す。 INL CST T& OPR[]( CST uint& num ) CST; INL T& OPR[]( CST uint& num ); INL CONST_UINT_REF GetSizeOfNode() CST NEX; INL CONST_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( CONST_UINT_REF i , CONST_UINT_REF j ) = delete; INL void SetNexttLink( CONST_UINT_REF i , CONST_UINT_REF j ) = delete; INL CONST_UINT_REF GetPreviousLinkIndex( CONST_UINT_REF i ) CST = delete; INL CONST_UINT_REF GetNexttLinkIndex( CONST_UINT_REF i ) CST = delete; CONST_UINT_REF DeLink( CONST_UINT_REF i ) = delete; void ReLink( CONST_UINT_REF i ) = delete; void Graft( CONST_UINT_REF num0 , CONST_UINT_REF num1 ); }; TMP INL UnionFindForest::UnionFindForest( CONST_UINT_REF max_size ) : LinkedVector >( max_size ) {} TMP INL CST VLSubTree& UnionFindForest::GetSubTree( CONST_UINT_REF num ) CST { RET LinkedVector >::OPR[]( num ).m_node; } TMP INL CONST_UINT_REF UnionFindForest::GetPredecessorNode( CONST_UINT_REF num ) CST { RET LinkedVector >::OPR[]( num ).m_pred_node; } TMP CONST_UINT_REF UnionFindForest::GetRootOfNode( CONST_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( CONST_UINT_REF num ) const { 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 CONST_UINT_REF UnionFindForest::GetSizeOfNode() CST NEX { RET LinkedVector >::GetSizeOfVector(); } TMP INL CONST_UINT_REF UnionFindForest::GetSizeOfRoot() CST NEX { RET LinkedVector >::GetSizeOfLink(); } TMP INL void UnionFindForest::push_RightMost() {} TMP void UnionFindForest::push_RightMost( CST T& t ) { EntryOfLinkedVector >& 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( CONST_UINT_REF num0 , CONST_UINT_REF num1 ) { CONST_UINT_REF e0_root_index = LinkedVector >::OPR[]( num0 ).m_root; CONST_UINT_REF e1_root_index = LinkedVector >::OPR[]( num1 ).m_root; if( e0_root_index == e1_root_index ){ RET; } EntryOfUnionFindForest& e0_root = LinkedVector >::OPR[]( e0_root_index ); EntryOfUnionFindForest& 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; EntryOfUnionFindForest* CST p_e_root[2] = { &e0_root , &e1_root }; EntryOfUnionFindForest& root_0 = *( p_e_root[i0] ); EntryOfUnionFindForest& 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; RET; } int main() { UNTIE; constexpr CST uint bound = 200001; CIN( uint , N ); assert( N < bound ); UnionFindForest f{ N }; FOR( i , 0 , N ){ f.push_RightMost( 0 ); } CIN( uint , M ); assert( M < bound ); int u[bound]; int v[bound]; int uvj; FOR( j , 0 , M ){ cin >> uvj; uvj--; u[j] = uvj; cin >> uvj; uvj--; v[j] = uvj; } while( M-- != 0 ){ CONST_INT_REF uj = u[M]; CONST_INT_REF vj = v[M]; CONST_UINT_REF uj_root = f.GetRootOfNode( uj ); CONST_UINT_REF vj_root = f.GetRootOfNode( vj ); int& count_0 = f[uj_root]; int& count_1 = f[vj_root]; if( count_0 < count_1 ){ count_0 = ++count_1; } else { count_1 = ++count_0; } f.Graft( uj_root , vj_root ); } RETURN( f[ f.GetRootOfNode( 0 ) ] ); }