1. 程式人生 > >【HDU】5957 Query on a graph【分類討論+bfs序線段樹】

【HDU】5957 Query on a graph【分類討論+bfs序線段樹】

水題

#include <bits/stdc++.h>
using namespace std ;

typedef long long LL ;
typedef pair < int , int > pii ;
typedef unsigned long long ULL ;

#define clr( a , x ) memset ( a , x , sizeof a )
#define root 1 , 1 , tot
#define ls o << 1
#define rs o << 1 | 1
#define lson ls , l , m
#define rson rs , m + 1 , r const int MAXN = 100005 ; LL sum[MAXN << 2] ; LL addv[MAXN << 2] ; vector < int > G[MAXN] ; int pre[MAXN] , vis[MAXN] ; int Q[MAXN] , head , tail ; pii pos[MAXN][3] ; int isroot[MAXN] ; int a[MAXN] , cnt ; int tot ; int n , q ; int get_circle ( int u ) { vis[u] = 1
; for ( int i = 0 ; i < G[u].size () ; ++ i ) { int v = G[u][i] ; if ( v == pre[u] ) continue ; pre[v] = u ; if ( vis[v] ) { cnt = 0 ; int x = u ; while ( x != v ) { a[++ cnt] = x ; isroot[x] = cnt ; x
= pre[x] ; } a[++ cnt] = v ; isroot[v] = cnt ; return 1 ; } if ( get_circle ( v ) ) return 1 ; } return 0 ; } void bfs ( int s ) { head = tail = 0 ; Q[tail ++] = s ; pre[s] = 0 ; while ( head != tail ) { int u = Q[head ++] ; ++ tot ; pos[u][0] = pii ( tot , tot ) ; pos[u][1] = pos[u][2] = pii ( MAXN , -1 ) ; for ( int i = 0 ; i < G[u].size () ; ++ i ) { int v = G[u][i] ; if ( v == pre[u] || isroot[v] ) continue ; pre[v] = u ; Q[tail ++] = v ; } } while ( head ) { int u = Q[-- head] ; int f = pre[u] , g = pre[f] ; if ( f ) { pos[f][1].first = min ( pos[f][1].first , pos[u][0].first ) ; pos[f][1].second = max ( pos[f][1].second , pos[u][0].second ) ; if ( g ) { pos[g][2].first = min ( pos[g][2].first , pos[u][0].first ) ; pos[g][2].second = max ( pos[g][2].second , pos[u][0].second ) ; } } } } void build ( int o , int l , int r ) { addv[o] = 0 ; sum[o] = 0 ; if ( l == r ) return ; int m = l + r >> 1 ; build ( lson ) ; build ( rson ) ; } void up ( int o ) { sum[o] = sum[ls] + sum[rs] ; } void down ( int o , int l , int r ) { if ( addv[o] ) { int m = l + r >> 1 ; addv[ls] += addv[o] ; addv[rs] += addv[o] ; sum[ls] += addv[o] * ( m - l + 1 ) ; sum[rs] += addv[o] * ( r - m ) ; addv[o] = 0 ; } } void update ( int L , int R , int v , int o , int l , int r ) { if ( L <= l && r <= R ) { sum[o] += v * ( r - l + 1 ) ; addv[o] += v ; return ; } down ( o , l , r ) ; int m = l + r >> 1 ; if ( L <= m ) update ( L , R , v , lson ) ; if ( m < R ) update ( L , R , v , rson ) ; up ( o ) ; } LL query ( int L , int R , int o , int l , int r ) { if ( L <= l && r <= R ) return sum[o] ; down ( o , l , r ) ; int m = l + r >> 1 ; if ( R <= m ) return query ( L , R , lson ) ; if ( m < L ) return query ( L , R , rson ) ; return query ( L , R , lson ) + query ( L , R , rson ) ; } void Update ( int x , int k , int d ) { if ( k < 0 ) return ; for ( int i = 0 ; i <= k ; ++ i ) { int l = pos[x][i].first , r = pos[x][i].second ; if ( l > r ) continue ; //printf ( "%d %d %d %d %d %d\n" , x , k , i , l , r , tot ) ; update ( l , r , d , root ) ; } } LL Query ( int x , int k ) { if ( k < 0 ) return 0 ; LL res = 0 ; for ( int i = 0 ; i <= k ; ++ i ) { int l = pos[x][i].first , r = pos[x][i].second ; if ( l > r ) continue ; res += query ( l , r , root ) ; } return res ; } void solve () { scanf ( "%d" , &n ) ; for ( int i = 1 ; i <= n ; ++ i ) { G[i].clear () ; isroot[i] = 0 ; vis[i] = 0 ; } for ( int i = 1 ; i <= n ; ++ i ) { int u , v ; scanf ( "%d%d" , &u , &v ) ; G[u].push_back ( v ) ; G[v].push_back ( u ) ; } pre[1] = 0 ; get_circle ( 1 ) ; tot = 0 ; for ( int i = 1 ; i <= cnt ; ++ i ) { bfs ( a[i] ) ; } build ( root ) ; scanf ( "%d" , &q ) ; while ( q -- ) { char op[10] ; int u , k , d ; scanf ( "%s%d%d" , op , &u , &k ) ; int f = pre[u] , g = pre[f] , now = 1 ; if ( !f ) now = isroot[u] ; else if ( !g ) now = isroot[f] ; int L = now == 1 ? cnt : now - 1 ; int R = now == cnt ? 1 : now + 1 ; int L2 = L == 1 ? cnt : L - 1 ; int R2 = R == cnt ? 1 : R + 1 ; L = a[L] ; R = a[R] ; L2 = a[L2] ; R2 = a[R2] ; //printf ( "%d %d %d %d %d %d\n" , f , g , L , R , L2 , R2 ) ; if ( op[0] == 'M' ) { scanf ( "%d" , &d ) ; if ( f ) { Update ( u , k , d ) ; Update ( f , k - 1 , d ) ; if ( k == 2 ) Update ( u , 0 , -d ) ; if ( g ) Update ( g , k - 2 , d ) ; else { Update ( L , k - 2 , d ) ; Update ( R , k - 2 , d ) ; } } else { Update ( u , k , d ) ; Update ( L , k - 1 , d ) ; Update ( R , k - 1 , d ) ; if ( cnt >= 4 ) { Update ( R2 , k - 2 , d ) ; if ( L2 != R2 ) Update ( L2 , k - 2 , d ) ; } } } else { LL ans = 0 ; if ( f ) { ans += Query ( u , k ) ; ans += Query ( f , k - 1 ) ; if ( k == 2 ) ans -= Query ( u , 0 ) ; if ( g ) ans += Query ( g , k - 2 ) ; else { ans += Query ( L , k - 2 ) ; ans += Query ( R , k - 2 ) ; } } else { ans += Query ( u , k ) ; ans += Query ( L , k - 1 ) ; ans += Query ( R , k - 1 ) ; if ( cnt >= 4 ) { ans += Query ( R2 , k - 2 ) ; if ( L2 != R2 ) ans += Query ( L2 , k - 2 ) ; } } printf ( "%lld\n" , ans ) ; } } } int main () { int T ; scanf ( "%d" , &T ) ; while ( T -- ) solve () ; return 0 ; }