您的位置:首页 > 其它

BZOJ 4034: [HAOI2015]T2( 树链剖分 )

2015-06-12 20:18 423 查看


树链剖分...子树的树链剖分序必定是一段区间 , 先记录一下就好了

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

#include<cstdio>#include<cstring>#include<algorithm>#include<iostream> #define rep( i , n ) for( int i = 0 ; i < n ; i++ )#define Rep( i , n ) for( int i = 1 ; i <= n ; ++i )#define clr( x , c ) memset( x , c , sizeof( x ) )#define REP( x ) for( edge* e = head[ x ] ; e ; e = e -> next ) using namespace std; typedef long long ll; const int maxn = 100000 + 5; int n , seq[ maxn ]; struct edge { int to; edge* next;}; edge* pt , EDGE[ maxn << 1 ];edge* head[ maxn ]; void edge_init() { pt = EDGE; clr( head , 0 );} void _add( int u , int v ) { pt -> to = v; pt -> next = head[ u ]; head[ u ] = pt++;} #define add_edge( u , v ) _add( u , v ) , _add( v , u ) int top[ maxn ] , fa[ maxn ] , size[ maxn ] , dep[ maxn ] , son[ maxn ];int id[ maxn ] , _id[ maxn ] , id_cnt = 0;int LEFT[ maxn ] , RIGHT[ maxn ]; void dfs( int x ) { size[ x ] = 1; REP( x ) { if( e -> to == fa[ x ] ) continue; fa[ e -> to ] = x; dep[ e -> to ] = dep[ x ] + 1; dfs( e -> to ); size[ x ] += size[ e -> to ]; if( son[ x ] == -1 || size[ e -> to ] > size[ son[ x ] ] ) son[ x ] = e -> to; }} int TOP;void DFS( int x ) { LEFT[ x ] = id[ x ] = ++id_cnt; _id[ id_cnt ] = x; top[ x ] = TOP; if( son[ x ] != -1 ) DFS( son[ x ] ); REP( x ) if( id[ e -> to ] < 0 ) DFS( TOP = e -> to ); RIGHT[ x ] = id_cnt;} void DFS_init() { clr( id , -1 ); clr( son , -1 ); dfs( dep[ 0 ] = 0 ); DFS( TOP = 0 );} ll add[ maxn << 2 ] , sum[ maxn << 2 ]; int op , L , R , v; #define mid( l , r ) ( l + r ) >> 1#define L( x ) ( x << 1 )#define R( x ) ( L( x ) ^ 1 ) void pushdown( int x , int l , int r ) { if( add[ x ] ) { add[ L( x ) ] += add[ x ]; add[ R( x ) ] += add[ x ]; add[ x ] = 0; }} void maintain( int x , int l , int r ) { if( r > l ) { sum[ x ] = sum[ L( x ) ] + sum[ R( x ) ] + add[ x ] * ( r - l + 1 ); } else { sum[ x ] += add[ x ]; add[ x ] = 0; }} void update( int x , int l , int r ) { if( L <= l && r <= R ) { add[ x ] += v; } else { pushdown( x , l , r ); int m = mid( l , r ); L <= m ? update( L( x ) , l , m ) : maintain( L( x ) , l , m ); m < R ? update( R( x ) , m + 1 , r ) : maintain( R( x ) , m + 1 , r ); } maintain( x , l , r );}void U( int l , int r ) { L = l , R = r; update( 1 , 1 , n );} ll query( int x , int l , int r ) { if( L <= l && r <= R ) return sum[ x ]; int m = mid( l , r ); pushdown( x , l , r ); maintain( L( x ) , l , m ); maintain( R( x ) , m + 1 , r ); return ( L <= m ? query( L( x ) , l , m ) : 0 ) + ( m < R ? query( R( x ) , m + 1 , r ) : 0 );}ll Q( int l , int r ) { L = l , R = r; return query( 1 , 1 , n );} void build( int x , int l , int r ) { if( l == r ) { sum[ x ] = seq[ _id[ l ] ]; } else { int m = mid( l , r ); build( L( x ) , l , m ); build( R( x ) , m + 1 , r ); maintain( x , l , r ); }} int X; ll Query() { ll ans = 0; while( top[ X ] != 0 ) { ans += Q( id[ top[ X ] ] , id[ X ] ); X = fa[ top[ X ] ]; } return ans + Q( id[ 0 ] , id[ X ] );} void modify() { if( op == 1 ) { U( id[ X ] , id[ X ] ); } else { U( LEFT[ X ] , RIGHT[ X ] ); }} int main() { freopen( "test.in" , "r" , stdin ); int m; cin >> n >> m; rep( i , n ) scanf( "%d" , seq + i ); edge_init(); rep( i , n - 1 ) { int u , v; scanf( "%d%d" , &u , &v ); u-- , v--; add_edge( u , v ); } DFS_init(); build( 1 , 1 , n ); while( m-- ) { scanf( "%d%d" , &op , &X ); X--; if( op == 3 ) { printf( "%lld\n" , Query() ); } else { scanf( "%d" , &v ); modify(); } } return 0;}

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

4034: [HAOI2015]T2

Time Limit: 10 Sec Memory Limit: 256 MB
Submit: 444 Solved: 181
[Submit][Status][Discuss]

Description

有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个

操作,分为三种:操作 1 :把某个节点 x 的点权增加 a 。操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。操作 3 :询问某个节点 x 到根的路径中所有点的点权和。

Input

第一行包含两个整数 N, M 。表示点数和操作数。

接下来一行 N 个整数,表示树中节点的初始权值。接下来 N-1 行每行三个正整数 fr, to , 表示该树中存在一条边 (fr, to) 。再接下来 M 行,每行分别表示一次操作。其中第一个数表示该操作的种类( 1-3 ) ,之后接这个操作的参数( x 或者 x a ) 。

Output

对于每个询问操作,输出该询问的答案。答案之间用换行隔开。

Sample Input

5 5
1 2 3 4 5
1 2
1 4
2 3
2 5
3 3
1 2 1
3 5
2 1 2
3 3

Sample Output

6
9
13

HINT

对于 100% 的数据, N,M<=100000 ,且所有输入数据的绝对值都不

会超过 10^6 。

Source

鸣谢bhiaibogf提供
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: