BZOJ 3282: Tree( LCT )
LCT..
--------------------------------------------------------------------------------
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define rep( i , n ) for( int i = 0 ; i < n ; ++i )
#define clr( x , c ) memset( x , c , sizeof( x ) )
using namespace std;
const int maxn = 300000 + 5;
const int maxnode = maxn + 100;
int n;
struct Node *pt , *null;
struct Node {
Node *ch[ 2 ] , *p , *fa;
int v , x;
bool rev , isRoot;
Node( int _v = 0 ) : v( _v ) , x( _v ) {
ch[ 0 ] = ch[ 1 ] = p = fa = null;
rev = false;
isRoot = true;
}
inline bool d() {
return this == p -> ch[ 1 ];
}
inline void setc( Node* c , int d ) {
ch[ d ] = c;
c -> p = this;
}
inline void relax() {
if( rev ) {
rev = false;
rep( i , 2 ) if( ch[ i ] != null )
ch[ i ] -> Rev();
}
}
inline void Rev() {
rev ^= 1;
swap( ch[ 0 ] , ch[ 1 ] );
}
inline void setRoot() {
fa = p;
p = null;
isRoot = true;
}
inline void upd() {
x = ch[ 0 ] -> x ^ v ^ ch[ 1 ] -> x;
}
void* operator new( size_t ) {
return pt++;
}
};
Node NODE[ maxnode ];
void rot( Node* t ) {
Node* p = t -> p;
p -> relax();
t -> relax();
int d = t -> d();
p -> p -> setc( t , p -> d() );
p -> setc( t -> ch[ d ^ 1 ] , d );
t -> setc( p , d ^ 1 );
p -> upd();
if( p -> isRoot ) {
p -> isRoot = false;
t -> isRoot = true;
t -> fa = p -> fa;
}
}
void splay( Node* t , Node* f = null ) {
static Node* S[ maxn ];
int top = 0;
for( Node* o = t ; o != null ; o = o -> p )
S[ ++top ] = o;
while( top )
S[ top-- ] -> relax();
for( Node* p = t -> p ; p != f ; p = t -> p ) {
if( p -> p != f )
p -> d() != t -> d() ? rot( t ) : rot( p );
rot( t );
}
t -> upd();
}
void access( Node* t ) {
for( Node* o = null ; t != null ; o = t , t = t -> fa ) {
splay( t );
t -> ch[ 1 ] -> setRoot();
t -> setc( o , 1 );
}
}
void makeRoot( Node* t ) {
access( t );
splay( t );
t -> Rev();
}
Node* findRoot( Node* t ) {
access( t );
splay( t );
for( ; t -> ch[ 0 ] != null ; t = t -> ch[ 0 ] )
t -> relax();
splay( t );
return t;
}
void join( Node* x , Node* y ) {
makeRoot( x );
x -> fa= y;
splay( y );
}
Node* get( Node* x , Node* y ) {
makeRoot( x );
access( y );
splay( y );
return y;
}
void cut( Node* x , Node* y ) {
makeRoot( x );
access( y );
splay( x );
x -> setc( null , 1 );
x -> upd();
y -> p = null;
y -> setRoot();
}
void init() {
pt = NODE;
null = new Node( 0 );
}
Node* V[ maxn ];
int main() {
freopen( "test.in" , "r" , stdin );
init();
int m;
cin >> n >> m;
rep( i , n ) {
int v;
scanf( "%d" , &v );
V[ i ] = new Node( v );
}
int x , y , op;
while( m-- ) {
scanf( "%d%d%d" , &op , &x , &y );
x-- , y--;
if( op == 3 ) {
y++;
access( V[ x ] );
splay( V[ x ] );
V[ x ] -> v = y;
V[ x ] -> upd();
} else if( ! op ) {
Node* t = get( V[ x ] , V[ y ] );
printf( "%d\n" , get( V[ x ] , V[ y ] ) -> x );
} else if( op == 1 ) {
if( findRoot( V[ x ] ) != findRoot( V[ y ] ) )
join( V[ x ] , V[ y ] );
} else {
if( findRoot( V[ x ] ) == findRoot( V[ y ] ) )
cut( V[ x ] , V[ y ] );
}
}
return 0;
}
--------------------------------------------------------------------------------
3282: Tree
Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 827 Solved: 341
[Submit][Status][Discuss]
Description
给定N个点以及每个点的权值,要你处理接下来的M个操作。操作有4种。操作从0到3编号。点从1到N编号。
0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和。保证x到y是联通的。
1:后接两个整数(x,y),代表连接x到y,若x到Y已经联通则无需连接。
2:后接两个整数(x,y),代表删除边(x,y),不保证边(x,y)存在。
3:后接两个整数(x,y),代表将点X上的权值变成Y。
Input
第1行两个整数,分别为N和M,代表点数和操作数。
第2行到第N+1行,每行一个整数,整数在[1,10^9]内,代表每个点的权值。
第N+2行到第N+M+1行,每行三个整数,分别代表操作类型和操作所需的量。
Output
对于每一个0号操作,你须输出X到Y的路径上点权的Xor和。
Sample Input
3 3
1
2
3
1 1 2
0 1 2
0 1 1
1
2
3
1 1 2
0 1 2
0 1 1
Sample Output
3
1
1
HINT
1<=N,M<=300000
Source