【HDU】5957 Query on a graph【分類討論+bfs序線段樹】
阿新 • • 發佈:2019-01-30
水題
#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 ;
}