CFR Educational 6 E. New Year Tree ( Timestamp + Segment Tree + bits )
Problem - E - Codeforces
It's instinctive to come up with timestamp and segment tree. Initially I thought it would be fine with sets to maintain the set of colours, but now it seems like it wouldn't work. Maybe it's because my segment tree is pointer-based, which is notoriously slow. Do it with bits instead, since there are at most 60 colours, long long int will do.
template< class T1 > int count_bit( T1 x ){ return x == 0 ? 0 : ( x & ( T1 )1 ) + count_bit( x >> ( T1 )1 ); } struct itvt{ ll col, col_tag; int lb, rb; itvt *lc, *rc; itvt( int _lb, int _rb ): col( 0 ), col_tag( 0 ), lc( NULL ), rc( NULL ){ lb = _lb, rb = _rb; } itvt* push(){ if( col_tag ) lc->col_tag = col_tag, lc->col = col_tag, rc->col_tag = col_tag, rc->col = col_tag, col_tag = 0; return this; } itvt* pull(){ col = lc->col | rc->col; return this; } void update( int ql, int qr, int c ){ if( qr < lb or rb < ql ) return; if( ql <= lb and rb <= qr ){ col_tag = 1LL << c; col = col_tag; return; } push(); lc->update( ql, qr, c ); rc->update( ql, qr, c ); pull(); } ll query( int ql, int qr ){ if( qr < lb or rb < ql ) return 0; if( ql <= lb and rb <= qr ) return col; push(); ll col_bar = 0; col_bar |= lc->query( ql, qr ); col_bar |= rc->query( ql, qr ); pull(); return col_bar; } }; itvt* build_itvt( int lb, int rb ){ itvt *t = new itvt( lb, rb ); if( lb == rb ) return t; int mid = lb + rb >> 1; t->lc = build_itvt( lb, mid ); t->rc = build_itvt( mid + 1, rb ); return t->pull(); } void dfs( int &tick, int u, int fa, vp &v_to_range, const vvi &G ){ v_to_range[ u ].first = ++tick; for( int v : G[ u ] ){ if( v == fa ) continue; dfs( tick, v, u, v_to_range, G ); } v_to_range[ u ].second = tick; } void solve(){ int N, M; cin >> N >> M; vi C( N ); for( int i = 0; i < N; ++i ) cin >> C[ i ], --C[ i ]; vvi G( N ); for( int i = 0; i < N - 1; ++i ){ int u, v; cin >> u >> v; G[ u - 1 ].push_back( v - 1 ); G[ v - 1 ].push_back( u - 1 ); } vp v_to_range( N ); int dfs_tick = -1; dfs( dfs_tick, 0, -1, v_to_range, G ); itvt *root = build_itvt( 0, N - 1 ); for( int i = 0; i < v_to_range.size(); ++i ) root->update( v_to_range[ i ].first, v_to_range[ i ].first, C[ i ] ); for( int i = 0; i < M; ++i ){ int op; cin >> op; if( op == 1 ){ int u, c; cin >> u >> c; --u, --c; root->update( v_to_range[ u ].first, v_to_range[ u ].second, c ); } else{ int u; cin >> u; --u; cout << count_bit( root->query( v_to_range[ u ].first, v_to_range[ u ].second ) ) << "\n"; } } }