传送门:【FZU】2082 过路费
传送门:裸的树链剖分。
代码如下:
#include <cmath> #include <cstdio> #include <cstring> #include <algorithm> using namespace std ; typedef long long LL ; #define travel( e , H , u ) for ( Edge* e = H[u] ; e ; e = e -> next ) #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 ) #define cpy( a , x ) memcpy ( a , x , sizeof a ) #define ls ( o << 1 ) #define rs ( o << 1 | 1 ) #define lson ls , l , m #define rson rs , m + 1 , r #define root 1 , 2 , n #define mid ( ( l + r ) >> 1 ) const int MAXN = 50005 ; const int MAXE = 100005 ; const int INF = 0x3f3f3f3f ; struct Edge { int v ; Edge* next ; } E[MAXE] , *H[MAXN] , *edge ; struct Line { int x , y , w ; Line () {} Line ( int x , int y , int w ) : x ( x ) , y ( y ) , w ( w ) {} } L[MAXN] ; LL sum[MAXN << 2] ; int siz[MAXN] ; int pos[MAXN] ; int pre[MAXN] ; int top[MAXN] ; int dep[MAXN] ; int son[MAXN] ; int val[MAXN] ; int tree_idx ; int n , q ; void clear () { edge = E ; tree_idx = 0 ; clr ( H , 0 ) ; pre[1] = 0 ; siz[0] = 0 ; dep[0] = 0 ; } void addedge ( int u , int v ) { edge -> v = v ; edge -> next = H[u] ; H[u] = edge ++ ; edge -> v = u ; edge -> next = H[v] ; H[v] = edge ++ ; } void dfs ( int u ) { siz[u] = 1 ; son[u] = 0 ; travel ( e , H , u ) { int v = e -> v ; if ( v != pre[u] ) { pre[v] = u ; dep[v] = dep[u] + 1 ; dfs ( v ) ; siz[u] += siz[v] ; if ( siz[v] > siz[son[u]] ) son[u] = v ; } } } void rewrite ( int u , int top_element ) { top[u] = top_element ; pos[u] = ++ tree_idx ; if ( son[u] ) rewrite ( son[u] , top_element ) ; travel ( e , H , u ) { int v = e -> v ; if ( v != son[u] && v != pre[u] ) rewrite ( v , v ) ; } } void build ( int o , int l , int r ) { if ( l == r ) { sum[o] = val[l] ; return ; } int m = mid ; build ( lson ) , build ( rson ) ; sum[o] = sum[ls] + sum[rs] ; } void modify ( int pos , int v , int o , int l , int r ) { while ( l != r ) { int m = mid ; if ( pos <= m ) r = m , o = ls ; else l = m + 1 , o = rs ; } sum[o] = v ; while ( o != 1 ) { o >>= 1 ; sum[o] = sum[ls] + sum[rs] ; } } LL sub_query ( int L , int R , int o , int l , int r ) { if ( L <= l && r <= R ) return sum[o] ; int m = mid ; if ( R <= m ) return sub_query ( L , R , lson ) ; if ( m < L ) return sub_query ( L , R , rson ) ; return sub_query ( L , R , lson ) + sub_query ( L , R , rson ) ; } LL query ( int x , int y , LL res = 0 ) { while ( top[x] != top[y] ) { if ( dep[top[x]] < dep[top[y]] ) swap ( x , y ) ; res += sub_query ( pos[top[x]] , pos[x] , root ) ; x = pre[top[x]] ; } if ( x == y ) return res ; if ( dep[x] > dep[y] ) swap ( x , y ) ; return res + sub_query ( pos[x] + 1 , pos[y] , root ) ; } void solve () { int op , x , y , w ; clear () ; rep ( i , 1 , n ) { scanf ( "%d%d%d" , &x , &y , &w ) ; L[i] = Line ( x , y , w ) ; addedge ( x , y ) ; } dfs ( 1 ) ; rewrite ( 1 , 1 ) ; rep ( i , 1 , n ) { if ( dep[L[i].x] < dep[L[i].y] ) swap ( L[i].x , L[i].y ) ; val[pos[L[i].x]] = L[i].w ; } build ( root ) ; while ( q -- ) { scanf ( "%d%d%d" , &op , &x , &y ) ; if ( op == 0 ) modify ( pos[L[x].x] , y , root ) ; else printf ( "%I64d\n" , query ( x , y ) ) ; } } int main () { while ( ~scanf ( "%d%d" , &n , &q ) ) solve () ; return 0 ; }