BZOJ 2631: tree( LCT )

LCT...略麻烦...

--------------------------------------------------------------------------------

#include<cstdio>
#include<algorithm>
#include<cstring>
#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 = 100000 + 5;
const int maxnode = maxn + 100;
const int MOD = 51061;
const int maxedge = maxn << 1;
 
#define mod( x ) ( ( x ) %= MOD )
 
int n;
 
struct edge {
int to;
edge* next;
};
 
edge* head[ maxn ];
edge EDGE[ maxedge ];
edge* e_pt;
 
void add( int u , int v ) {
e_pt -> to = v;
e_pt -> next = head[ u ];
head[ u ] = e_pt++;
}
 
#define add_edge( u , v ) add( u , v ) , add( v , u )
 
void edge_init() {
e_pt = EDGE;
clr( head , 0 );
}
 
struct Node *pt , *null;
 
struct Node {
Node *ch[ 2 ] , *p , *fa;
int add , mul , sum , v , s;
bool isRoot , rev;
Node() : v( 1 ) , add( 0 ) , mul( 1 ) , sum( 1 ) , s( 1 ) {
ch[ 0 ] = ch[ 1 ] = p = fa = null;
isRoot = true;
rev = false;
}
inline void setc( Node* c , int d ) {
ch[ d ] = c;
c -> p = this;
}
inline bool d() {
return this == p -> ch[ 1 ];
}
inline void relax() {
if( rev ) {
rev = false;
rep( i , 2 ) if( ch[ i ] != null )
   ch[ i ] -> Rev();
}
if( mul != 1 ) {
rep( i , 2 ) if( ch[ i ] != null ) 
   ch[ i ] -> Mul( mul );
mul = 1;
}
if( add ) {
rep( i , 2 ) if( ch[ i ] != null )
   ch[ i ] -> Add( add );
add = 0;
}
}
inline void upd() {
s = ch[ 0 ] -> s + ch[ 1 ] -> s + 1;
mod( sum = ch[ 0 ] -> sum + v + ch[ 1 ] -> sum );
}
inline void Rev() {
rev ^= 1;
swap( ch[ 0 ] , ch[ 1 ] );
}
inline void Add( int ad ) {
mod( add += ad );
mod( sum += 1LL * ad * s % MOD );
mod( v += ad );
}
inline void Mul( int mu ) {
add = 1LL * add * mu % MOD;
mul = 1LL * mul * mu % MOD;
sum = 1LL * sum * mu % MOD;
v = 1LL * v * mu % MOD;
}
inline void setRoot() {
fa = p;
p = null;
isRoot = true;
}
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 cut( Node* x , Node* y ) {
makeRoot( x );
access( y );
splay( x );
x -> setc( null , 1 );
x -> upd();
y -> p = null;
y -> setRoot();
}
 
void join( Node* x , Node* y ) {
makeRoot( x );
x -> fa = y;
}
 
Node* get( Node* x , Node* y ) {
makeRoot( x );
access( y );
splay( y );
return y;
}
 
void node_init() {
pt = NODE;
null = new( Node );
null -> s = null -> v = null -> sum = 0;
}
 
Node* V[ maxn ];
 
void dfs( int x , int par ) {
for( edge* e = head[ x ] ; e ; e = e -> next ) {
int to = e -> to;
if( to == par ) continue;
dfs( to , x );
V[ to ] -> fa = V[ x ];
}
}
 
void build_tree() {
rep( i , n ) V[ i ] = new( Node );
dfs( 0 , -1 );
}
 
int main() {
freopen( "test.in" , "r" , stdin );
freopen( "test.out" , "w" , stdout );
edge_init();
node_init();
int q , u , v;
cin >> n >> q;
rep( i , n - 1 ) {
scanf( "%d%d" , &u , &v );
u-- , v--;
add_edge( u , v );
}
build_tree();
char op;
while( q-- ) {
scanf( " %c%d%d" , &op , &u , &v );
u-- , v--;
if( op == '-' ) {
cut( V[ u ] , V[ v ] );
scanf( "%d%d" , &u , &v );
u-- , v--;
join( V[ u ] , V[ v ] );
} else if( op == '/' ) {
printf( "%d\n" , get( V[ u ] , V[ v ] ) -> sum );
} else {
int c;
scanf( "%d" , &c );
mod( c );
op != '+' ? get( V[ u ] , V[ v ] ) -> Mul( c ) : get( V[ u ] , V[ v ] ) -> Add( c );
}
}
return 0;
}

 

-------------------------------------------------------------------------------- 

2631: tree

Time Limit: 30 Sec  Memory Limit: 128 MB
Submit: 2454  Solved: 819
[Submit][Status][Discuss]

Description

 一棵n个点的树,每个点的初始权值为1。对于这棵树有q个操作,每个操作为以下四种操作之一:
+ u v c:将u到v的路径上的点的权值都加上自然数c;
- u1 v1 u2 v2:将树中原有的边(u1,v1)删除,加入一条新边(u2,v2),保证操作完之后仍然是一棵树;
* u v c:将u到v的路径上的点的权值都乘上自然数c;
/ u v:询问u到v的路径上的点的权值和,求出答案对于51061的余数。

Input

  第一行两个整数n,q
接下来n-1行每行两个正整数u,v,描述这棵树
接下来q行,每行描述一个操作

Output

  对于每个/对应的答案输出一行

Sample Input

3 2
1 2
2 3
* 1 3 4
/ 1 1

Sample Output

4


HINT

数据规模和约定

10%的数据保证,1<=n,q<=2000

另外15%的数据保证,1<=n,q<=5*10^4,没有-操作,并且初始树为一条链

另外35%的数据保证,1<=n,q<=5*10^4,没有-操作

100%的数据保证,1<=n,q<=10^5,0<=c<=10^4


Source

 

posted @ 2015-06-24 21:07  JSZX11556  阅读(242)  评论(0编辑  收藏  举报