传送门:【BZOJ】2631 tree
题目分析:LCT模板题~标记的维护和维护线段类似。
代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
#define rep( i , a , b ) for ( int i = ( a ) ;i < ( b ) ;++ i )
#define rev( i , a , b ) for ( int i = ( a ) ;i >= ( b ) ;-- i )
#define For( i , a , b ) for ( int i = ( a ) ;i <= ( b ) ;++ i )
#define clr( a , x ) memset ( a , x , sizeof a )
typedef long long LL ;
const int MAXN = 100005 ;
const LL mod = 51061 ;
struct Node* null ;
struct Node {
Node* c[2] ;
Node* f ;
int flip ;
LL addv ;
LL mulv ;
LL size ;
LL sum ;
LL v ;
void newnode ( int val ) {
addv = 0 ;
mulv = 1 ;
size = 1 ;
flip = 0 ;
v = val ;
sum = val ;
f = null ;
c[0] = c[1] = null ;
}
void mul_val ( LL val ) {
if ( this == null ) return ;
v *= val ;
sum *= val ;
addv *= val ;
mulv *= val ;
if ( v >= mod ) v %= mod ;
if ( sum >= mod ) sum %= mod ;
if ( addv >= mod ) addv %= mod ;
if ( mulv >= mod ) mulv %= mod ;
}
void add_val ( LL val ) {
if ( this == null ) return ;
v += val ;
sum += size * val ;
addv += val ;
if ( v >= mod ) v %= mod ;
if ( sum >= mod ) sum %= mod ;
if ( addv >= mod ) addv %= mod ;
}
void reverse () {
std :: swap ( c[0] , c[1] ) ;
flip ^= 1 ;
}
void push_up () {
size = 1 + c[0]->size + c[1]->size ;
sum = ( c[0]->sum + c[1]->sum + v ) % mod ;
}
void push_down () {
if ( flip ) {
c[0]->reverse () ;
c[1]->reverse () ;
flip = 0 ;
}
if ( 1 != mulv ) {
c[0]->mul_val ( mulv ) ;
c[1]->mul_val ( mulv ) ;
mulv = 1 ;
}
if ( addv ) {
c[0]->add_val ( addv ) ;
c[1]->add_val ( addv ) ;
addv = 0 ;
}
}
void link_child ( Node* o , int d ) {
c[d] = o ;
o->f = this ;
}
int is_root () {
return f == null || f->c[0] != this && f->c[1] != this ;
}
void rotate ( int d ) {
Node* p = f ;
Node* gp = p->f ;
p->link_child ( c[d] , !d ) ;
if ( !p->is_root () ) {
if ( p == gp->c[0] ) gp->link_child ( this , 0 ) ;
else gp->link_child ( this , 1 ) ;
}else f = gp ;
link_child ( p , d ) ;
p->push_up () ;
}
void down () {
if ( !is_root () ) f->down () ;
push_down () ;
}
void splay () {
down () ;
while ( !is_root () ) {
if ( f->is_root () ) {
if ( this == f->c[0] ) rotate ( 1 ) ;
else rotate ( 0 ) ;
}else {
if ( f == f->f->c[0] ) {
if ( this == f->c[0] ) f->rotate ( 1 ) , rotate ( 1 ) ;
else rotate ( 0 ) , rotate ( 1 ) ;
}else {
if ( this == f->c[1] ) f->rotate ( 0 ) , rotate ( 0 ) ;
else rotate ( 1 ) , rotate ( 0 ) ;
}
}
}
push_up () ;
}
void access () {
Node* o = this ;
Node* x = null ;
while ( o != null ) {
o->splay () ;
o->link_child ( x , 1 ) ;
o->push_up () ;
x = o ;
o = o->f ;
}
splay () ;
}
void make_root () {
access () ;
reverse () ;
}
Node* find_root () {
access () ;
Node* o = this ;
while ( o->c[0] != null ) {
o->push_down () ;
o = o->c[0] ;
}
return o ;
}
void cut () {
access () ;
c[0]->f = null ;
c[0] = null ;
push_up () ;
}
void cut ( Node* o ) {
make_root () ;
o->cut () ;
}
void link ( Node* o ) {
make_root () ;
f = o ;
}
void add ( Node* o , int val ) {
make_root () ;
o->access () ;
o->add_val ( val ) ;
}
void mul ( Node* o , int val ) {
make_root () ;
o->access () ;
o->mul_val ( val ) ;
}
int query ( Node* o ) {
make_root () ;
o->access () ;
return o->sum ;
}
};
Node memory_pool[MAXN] ;
Node* cur ;
Node* node[MAXN] ;
int n , q ;
void clear () {
cur = memory_pool ;
null = cur ++ ;
null->newnode ( 0 ) ;
null->size = 0 ;
}
void solve () {
int u , v , x , y , val ;
char buf[10] ;
clear () ;
For ( i , 1 , n ) {
node[i] = cur ++ ;
node[i]->newnode ( 1 ) ;
}
rep ( i , 1 , n ) {
scanf ( "%d%d" , &u , &v ) ;
node[u]->link ( node[v] ) ;
}
while ( q -- ) {
scanf ( "%s" , buf ) ;
if ( buf[0] == '+' ) {
scanf ( "%d%d%d" , &x , &y , &val ) ;
node[x]->add ( node[y] , val ) ;
}else if ( buf[0] == '-' ) {
scanf ( "%d%d%d%d" , &x , &y , &u , &v ) ;
node[x]->cut ( node[y] ) ;
node[u]->link ( node[v] ) ;
}else if ( buf[0] == '*' ) {
scanf ( "%d%d%d" , &x , &y , &val ) ;
node[x]->mul ( node[y] , val ) ;
}else {
scanf ( "%d%d" , &x , &y ) ;
printf ( "%d\n" , node[x]->query ( node[y] ) ) ;
}
}
}
int main () {
scanf ( "%d%d" , &n , &q );solve () ;
return 0 ;
}