# BZOJ 3531: [Sdoi2014]旅行( 树链剖分 )

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

#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 ) )
#define Rep( i , n ) for( int i = 1 ; i <= n ; ++i )
#define REP( x ) for( edge* e = head[ x ] ; e ; e = e -> next )

using namespace std;

const int maxn = 100000 + 5;
const int maxre = int( 1e4 ) + 5;
const int maxedge = maxn << 1;
const int maxnode = int( 1e7 );

int n;

struct edge {
int to;
edge* next;
};

edge* head[ maxn ] , EDGE[ maxedge ];
edge* pt;

inline void add( int u , int v ) {
pt -> to = v;
pt -> next = head[ u ];
}
#define add_edge( u , v ) add( u , v ) , add( v , u )

void init() {
pt = EDGE;
}

int size[ maxn ] , dep[ maxn ] , fa[ maxn ] , son[ maxn ] , top[ maxn ];

void dfs( int x ) {
son[ x ] = -1;
size[ x ] = 1;
REP( x ) {
int to = e -> to;
if( to == fa[ x ] ) continue;
dep[ to ] = dep[ x ] + 1;
fa[ to ] = x;
dfs( to );
size[ x ] += size[ to ];
if( son[ x ] == -1 || size[ to ] > size[ son[ x ] ] )
son[ x ] = to;
}
}

int id_cnt , id[ maxn ] , TOP;

void DFS( int x ) {
id[ x ] = ++id_cnt;
top[ x ] = TOP;
if( son[ x ] != -1 ) DFS( son[ x ] );
REP( x ) {
int to = e -> to;
if( to == fa[ x ] || to == son[ x ] ) continue;
DFS( TOP = to );
}
}

void dfs_init() {
dfs( dep[ 0 ] = 0 );
DFS( TOP = 0 );
}

struct Node {
int ch[ 2 ];
int mx , sum;
Node() {
ch[ 0 ] = ch[ 1 ] = mx = sum = 0;
}
};

Node tree[ maxnode ];
int cnt = 1;
#define M( l , r ) ( ( l + r ) >> 1 )
int p , w;

void upd( int x ) {
Node &o = tree[ x ] , &L = tree[ o.ch[ 0 ] ] , &R = tree[ o.ch[ 1 ] ];
o.mx = max( L.mx , R.mx );
o.sum = L.sum + R.sum;
}

void modify( int &x , int l , int r ) {
if( ! x ) x = cnt++;
Node &o = tree[ x ];
if( p == l && p == r ) {
o.mx = o.sum = w;
} else {
int m = M( l , r );
p <= m ? modify( o.ch[ 0 ] , l , m ) : modify( o.ch[ 1 ] , m + 1 , r );
upd( x );
}
}

int L , R;
char op;// S sum , M max

int query( int x , int l , int r ) {
if( ! x ) return 0;
Node &o = tree[ x ];
if( L <= l && r <= R )
return op != 'S' ? o.mx : o.sum;
int m = M( l , r );
if( op == 'S' ) return ( L <= m ? query( o.ch[ 0 ] , l , m ) : 0 ) + ( m < R ? query( o.ch[ 1 ] , m + 1 , r ) : 0 );
else return max( L <= m ? query( o.ch[ 0 ] , l , m ) : 0 , m < R ? query( o.ch[ 1 ] , m + 1 , r ) : 0 );
}

int h[ maxre ];
int re[ maxn ]; //religion
int le[ maxn ]; //level

int Q_M( int x , int y ) {
int res = 0 , T = re[ x ];
while( top[ x ] != top[ y ] ) {
if( dep[ top[ x ] ] < dep[ top[ y ] ] ) swap( x , y );
L = id[ top[ x ] ] , R = id[ x ];
res = max( res , query( h[ T ] , 1 , n ) );
x = fa[ top[ x ] ];
}
if( dep[ x ] > dep[ y ] ) swap( x , y );
L = id[ x ] , R = id[ y ];
return max( res , query( h[ T ] , 1 , n ) );
}

int Q_S( int x , int y ) {
int res = 0 , T = re[ x ];
while( top[ x ] != top[ y ] ) {
if( dep[ top[ x ] ] < dep[ top[ y ] ] ) swap( x , y );
L = id[ top[ x ] ] , R = id[ x ];
res += query( h[ T ] , 1 , n );
x = fa[ top[ x ] ];
}
if( dep[ x ] > dep[ y ] ) swap( x , y );
L = id[ x ] , R = id[ y ];
return res + query( h[ T ] , 1 , n );
}

int main() {
freopen( "test.in" , "r" , stdin );
init();
int m;
cin >> n >> m;
rep( i , maxre ) h[ i ] = cnt++;
rep( i , n )
scanf( "%d%d" , le + i , re + i );
rep( i , n - 1 ) {
int u , v;
scanf( "%d%d" , &u , &v );
u-- , v--;
}
dfs_init();
// rep( i , n ) cout << id[ i ] << ' ';
// cout << "\n";
rep( i , n ) {
w = *( le + i );
p = id[ i ];
modify( h[ *( re + i ) ] , 1 , n );
}
char typ;
int x , y;
while( m-- ) {
scanf( " %c%c%d%d" , &typ , &op , &x , &y );
// cout << typ << ' ' << op << "\n";
x--;
if( typ == 'Q' )
y-- , printf( "%d\n" , op == 'S' ? Q_S( x , y ) : Q_M( x , y ) );
else
if( op == 'C' ) {
w = 0;
p = id[ x ];
modify( h[ re[ x ] ] , 1 , n );
re[ x ] = y;
w = le[ x ];
modify( h[ y ] , 1 , n );
} else {
le[ x ] = w = y;
p = id[ x ];
modify( h[ re[ x ] ] , 1 , n );
}
}

return 0;
}

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

## 3531: [Sdoi2014]旅行

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 669  Solved: 346
[Submit][Status][Discuss]

## Description

S国有N个城市，编号从1到N。城市间用N-1条双向道路连接，满足

在S国的历史上常会发生以下几种事件：
”CC x c”：城市x的居民全体改信了c教；
”CW x w”：城市x的评级调整为w;
”QS x y”：一位旅行者从城市x出发，到城市y，并记下了途中留宿过的城市的评级总和；
”QM x y”：一位旅行者从城市x出发，到城市y，并记下了途中留宿过

由于年代久远，旅行者记下的数字已经遗失了，但记录开始之前每座城市的信仰与评级，还有事件记录本身是完好的。请根据这些信息，还原旅行者记下的数字。    为了方便，我们认为事件之间的间隔足够长，以致在任意一次旅行中，所有城市的评级和信仰保持不变。

## Input

输入的第一行包含整数N，Q依次表示城市数和事件数。
接下来N行，第i+l行两个整数Wi，Ci依次表示记录开始之前，城市i的

接下来N-1行每行两个整数x，y表示一条双向道路。
接下来Q行，每行一个操作，格式如上所述。

## Output

对每个QS和QM事件，输出一行，表示旅行者记下的数字。

5 6
3 1
2 3
1 2
3 3
5 1
1 2
1 3
3 4
3 5
QS 1 5
CC 3 1
QS 1 5
CW 3 3
QS 1 5
QM 2 4

8
9
11
3

## HINT

N，Q < =10^5    ， C < =10^5

数据保证对所有QS和QM事件，起点和终点城市的信仰相同；在任意时

## Source

posted @ 2015-06-22 21:54  JSZX11556  阅读(163)  评论(0编辑  收藏  举报