题目链接: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 <cstdio> #include <cstring> #include <algorithm> 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 ; }
时间: 2025-01-02 03:34:23