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

題目鏈接: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 , 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 ;
}
發佈了718 篇原創文章 · 獲贊 37 · 訪問量 64萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章