【HDU】5957 Query on a graph【分类讨论+bfs序线段树】

来源:互联网 发布:华美淘宝客卷皮7.0 编辑:程序博客网 时间:2024/06/06 14:26

题目链接:Query on a graph

水题

#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 , rconst 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 ;}
0 0