P5354 [Ynoi2017] 由乃的 OJ
阿新 • • 發佈:2021-10-23
#include <cstdio> #include <vector> #include <iostream> using namespace std; #define ull unsigned long long #define pii pair< ull , int > #define fi first #define sc second #define mp make_pair const int MAXN = 1e5; int n , m , k; pii val[ MAXN + 5 ]; vector< int > Graph[ MAXN + 5 ]; int fa[ MAXN + 5 ] , hs[ MAXN + 5 ] , dep[ MAXN + 5 ] , siz[ MAXN + 5 ]; void dfs1( int u , int fat ) { fa[ u ] = fat; dep[ u ] = dep[ fat ] + 1; siz[ u ] = 1; for( int v : Graph[ u ] ) if( v != fa[ u ] ) { dfs1( v , u ); siz[ u ] += siz[ v ]; if( siz[ hs[ u ] ] < siz[ v ] ) hs[ u ] = v; } } int tim , dfn[ MAXN + 5 ] , rk[ MAXN + 5 ] , top[ MAXN + 5 ]; void dfs2( int u , int tp ) { dfn[ u ] = ++ tim , rk[ tim ] = u; top[ u ] = tp; if( hs[ u ] ) dfs2( hs[ u ] , tp ); for( int v : Graph[ u ] ) if( v != fa[ u ] && v != hs[ u ] ) dfs2( v , v ); } ull op( bool a , bool b , int op ) { if( op == 1 ) return a & b; if( op == 2 ) return a | b; if( op == 3 ) return a ^ b; } struct node { ull a[ 2 ][ 2 ]; node operator + ( const node &o ) const { node r; r.a[ 0 ][ 0 ] = ( a[ 0 ][ 0 ] & o.a[ 0 ][ 1 ] ) | ( ( ~a[ 0 ][ 0 ] ) & o.a[ 0 ][ 0 ] ); r.a[ 0 ][ 1 ] = ( a[ 0 ][ 1 ] & o.a[ 0 ][ 1 ] ) | ( ( ~a[ 0 ][ 1 ] ) & o.a[ 0 ][ 0 ] ); r.a[ 1 ][ 0 ] = ( o.a[ 1 ][ 0 ] & a[ 1 ][ 1 ] ) | ( ( ~o.a[ 1 ][ 0 ] ) & a[ 1 ][ 0 ] ); r.a[ 1 ][ 1 ] = ( o.a[ 1 ][ 1 ] & a[ 1 ][ 1 ] ) | ( ( ~o.a[ 1 ][ 1 ] ) & a[ 1 ][ 0 ] ); return r; } }; struct Segment_Tree { node Tree[ 4 * MAXN + 5 ]; #define ls x << 1 #define rs x << 1 | 1 #define mid ( l + r >> 1 ) void Build( int x , int l = 1 , int r = n ) { if( l == r ) { for( int i = 0 ; i < k ; i ++ ) { Tree[ x ].a[ 0 ][ 0 ] |= op( ( val[ rk[ l ] ].fi >> i ) & 1 , 0 , val[ rk[ l ] ].sc ) << i; Tree[ x ].a[ 1 ][ 0 ] |= op( ( val[ rk[ l ] ].fi >> i ) & 1 , 0 , val[ rk[ l ] ].sc ) << i; Tree[ x ].a[ 0 ][ 1 ] |= op( ( val[ rk[ l ] ].fi >> i ) & 1 , 1 , val[ rk[ l ] ].sc ) << i; Tree[ x ].a[ 1 ][ 1 ] |= op( ( val[ rk[ l ] ].fi >> i ) & 1 , 1 , val[ rk[ l ] ].sc ) << i; } return; } Build( ls , l , mid ); Build( rs , mid + 1 , r ); Tree[ x ] = Tree[ ls ] + Tree[ rs ]; } void Update( int x , int pos , int l = 1 , int r = n ) { if( pos < l || pos > r ) return; if( l == r ) { Tree[ x ].a[ 0 ][ 0 ] = Tree[ x ].a[ 1 ][ 0 ] = Tree[ x ].a[ 0 ][ 1 ] = Tree[ x ].a[ 1 ][ 1 ] = 0; for( int i = 0 ; i < k ; i ++ ) { Tree[ x ].a[ 0 ][ 0 ] |= op( ( val[ rk[ l ] ].fi >> i ) & 1 , 0 , val[ rk[ l ] ].sc ) << i; Tree[ x ].a[ 1 ][ 0 ] |= op( ( val[ rk[ l ] ].fi >> i ) & 1 , 0 , val[ rk[ l ] ].sc ) << i; Tree[ x ].a[ 0 ][ 1 ] |= op( ( val[ rk[ l ] ].fi >> i ) & 1 , 1 , val[ rk[ l ] ].sc ) << i; Tree[ x ].a[ 1 ][ 1 ] |= op( ( val[ rk[ l ] ].fi >> i ) & 1 , 1 , val[ rk[ l ] ].sc ) << i; } return; } Update( ls , pos , l , mid ); Update( rs , pos , mid + 1 , r ); Tree[ x ] = Tree[ ls ] + Tree[ rs ]; } node Query( int x , int ql , int qr , int l = 1 , int r = n ) { if( ql <= l && r <= qr ) return Tree[ x ]; if( qr <= mid ) return Query( ls , ql , qr , l , mid ); if( ql > mid ) return Query( rs , ql , qr , mid + 1 , r ); return Query( ls , ql , qr , l , mid ) + Query( rs , ql , qr , mid + 1 , r ); } }Tr; ull Query( int u , int v , ull mxw ) { node l , r , s; bool lf = 0 , rf = 0; while( top[ u ] != top[ v ] ) { if( dep[ top[ u ] ] < dep[ top[ v ] ] ) { //v node p = Tr.Query( 1 , dfn[ top[ v ] ] , dfn[ v ] ); if( !rf ) r = p , rf = 1; else r = p + r; v = fa[ top[ v ] ]; } else { //u node p = Tr.Query( 1 , dfn[ top[ u ] ] , dfn[ u ] ); if( !lf ) l = p , lf = 1; else l = p + l; u = fa[ top[ u ] ]; } } if( dep[ u ] < dep[ v ] ) { node p = Tr.Query( 1 , dfn[ u ] , dfn[ v ] ); if( !rf ) r = p , rf = 1; else r = p + r; } else { node p = Tr.Query( 1 , dfn[ v ] , dfn[ u ] ); if( !lf ) l = p , lf = 1; else l = p + l; } swap( l.a[ 0 ] , l.a[ 1 ] ); if( lf && rf ) s = l + r; if( !lf ) s = r; if( !rf ) s = l; ull Ans = 0; for( int i = k - 1 ; i >= 0 ; i -- ) { if( ( s.a[ 0 ][ 0 ] >> i ) & 1 ) Ans += 1llu << i; else if( ( ( s.a[ 0 ][ 1 ] >> i ) & 1 ) && mxw >= ( 1llu << i ) ) { mxw -= 1llu << i , Ans += 1llu << i; } } return Ans; } int main( ) { scanf("%d %d %d",&n,&m,&k); for( int i = 1 ; i <= n ; i ++ ) scanf("%d %llu",&val[ i ].sc,&val[ i ].fi); for( int i = 1 , u , v ; i < n ; i ++ ) { scanf("%d %d",&u,&v); Graph[ u ].push_back( v ); Graph[ v ].push_back( u ); } dfs1( 1 , 0 ); dfs2( 1 , 1 ); Tr.Build( 1 ); for( int i = 1 , op , x , y ; i <= m ; i ++ ) { ull z; scanf("%d %d %d %llu",&op,&x,&y,&z); if( op == 1 ) printf("%llu\n", Query( x , y , z ) ); if( op == 2 ) val[ x ] = mp( z , y ) , Tr.Update( 1 , dfn[ x ] ); } return 0; }