题目链接:hdu--3966
给出n个点的值,还有n-1条边的连接方式,三种操作:
1、I在节点a到b的路径中所有的点都增加x
2、D在节点a到b的路径中所有的点都减少x
3、Q询问第k个节点的值。
将每个节点的值转化为父节点到子节点的边的权值,对于根节点做一个虚拟的父节点0 。进行树链剖分,整合到线段树中之后注意:
更新时,不能只更新a到b上的边的权值,因为那样会使b节点的权值不能被更新到,在更新a到b的段的权值后,应该在更新b到b的权值。
#include
#include
#include
using namespace std ;
#define INF 0x3f3f3f3f
#define int_now int l,int r,int rt
#define now l,r,rt
#define lson l,(l+r)/2,rt<<1
#define rson (l+r)/2+1,r,rt<<1|1
#define maxn 100000
#pragma comment(linker, "/STACK:1024000000,1024000000")
struct node
{
int u , v ;
int next ;
} edge[maxn<<1];
int head[maxn] , cnt , vis[maxn] ;
int num[maxn] , dep[maxn] , fa[maxn] , son[maxn] , top[maxn] , w[maxn] , step ;
int cl[maxn<<2] , lazy[maxn<<2] ;
int c[maxn] , belong[maxn] ;
void add(int u,int v)
{
edge[cnt].u = u ;
edge[cnt].v = v ;
edge[cnt].next = head[u] ;
head[u] = cnt++ ;
return ;
}
void dfs1(int u)
{
num[u] = 1 ;
son[u] = -1 ;
int i , v ;
for(i = head[u] ; i != -1 ; i = edge[i].next)
{
v = edge[i].v ;
if( vis[v] ) continue ;
vis[v] = 1 ;
dep[v] = dep[u] + 1 ;
fa[v] = u ;
dfs1(v) ;
num[u] += num[v] ;
if( son[u] == -1 || num[ son[u] ] < num[v] )
son[u] = v ;
}
return ;
}
void dfs2(int u)
{
if( son[u] == -1 ) return ;
w[ son[u] ] = step++ ;
top[ son[u] ] = top[u] ;
vis[ son[u] ] = 1 ;
dfs2(son[u]) ;
int i , v ;
for(i = head[u] ; i != -1 ; i = edge[i].next)
{
v = edge[i].v ;
if( vis[v] ) continue ;
vis[v] = 1 ;
w[v] = step++ ;
top[v] = v ;
dfs2(v) ;
}
return ;
}
void dfs()
{
memset(vis,0,sizeof(vis)) ;
vis[0] = 1 ;
dep[0] = 1 ;
fa[0] = -1 ;
dfs1(0) ;
memset(vis,0,sizeof(vis)) ;
vis[0] = 1 ;
top[0] = 0 ;
step = 1 ;
dfs2(0) ;
return ;
}
void build(int_now)
{
cl[rt] = lazy[rt] = 0 ;
if( l == r )
{
cl[rt] = c[ belong[l] ] ;
return ;
}
build(lson) ;
build(rson) ;
return ;
}
void update(int ll,int rr,int_now,int x)
{
if( l > rr || r < ll ) return ;
if( ll <= l && rr >= r )
{
lazy[rt] += x ;
return ;
}
update(ll,rr,lson,x) ;
update(ll,rr,rson,x) ;
}
int query(int k,int_now,int sum)
{
sum += lazy[rt] ;
if( l == k && r == k )
{
return cl[rt] + sum ;
}
if( k <= (l+r)/2 )
return query(k,lson,sum) ;
else
return query(k,rson,sum) ;
}
void solve(int u,int v,int s)
{
int f1 , f2 ;
while( u != v )
{
if( dep[u] > dep[v] )
swap(u,v) ;
f1 = top[u] ;
f2 = top[v] ;
if( f1 == f2 )
{
update(w[son[u]],w[v],1,step-1,1,s) ;
v = u ;
}
else if( dep[f1] > dep[f2] )
{
update(w[f1],w[u],1,step-1,1,s) ;
u = fa[f1] ;
}
else
{
update(w[f2],w[v],1,step-1,1,s) ;
v = fa[f2] ;
}
}
update(w[u],w[u],1,step-1,1,s) ;
return ;
}
char str[10] ;
int main()
{
int n , m , p ;
int i , j , k ;
int u , v , s ;
while( scanf("%d %d %d", &n, &m, &p) != EOF )
{
memset(head,-1,sizeof(head)) ;
cnt = 0 ;
for(i = 1 ; i <= n ; i++)
scanf("%d", &c[i]) ;
add(0,1) , add(1,0) ;
while( m-- )
{
scanf("%d %d", &u, &v) ;
add(u,v) ;
add(v,u) ;
}
dfs() ;
for(i = 1 ; i <= n ; i++)
belong[ w[i] ] = i ;
build(1,step-1,1) ;
while( p-- )
{
scanf("%s", str) ;
if( str[0] == 'I' )
{
scanf("%d %d %d", &u, &v, &s) ;
solve(u,v,s) ;
}
else if( str[0] == 'D' )
{
scanf("%d %d %d", &u, &v, &s) ;
solve(u,v,-s) ;
}
else
{
scanf("%d", &i) ;
printf("%d\n", query(w[i],1,step-1,1,0)) ;
}
}
}
return 0 ;
}