1. 程式人生 > 其它 >P5354 [Ynoi2017] 由乃的 OJ

P5354 [Ynoi2017] 由乃的 OJ

#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;
}