树连剖分,线段树
树链剖分的核心就是将树线性化,从而简化对其的操作
#include <stdio.h> #include <vector> #include <string.h> #include <algorithm> using namespace std; typedef long long ll; const int MAXN = 50010; #ifndef __GNUC__ #pragma comment(linker, "/STACK:1024000000,1024000000") #endif // __GNUC__ int n, m, q; int cn_tree; struct _edge { int to, next; }edge[MAXN<<1]; int head[MAXN], cn_edge; int son[MAXN], siz[MAXN], top[MAXN], fa[MAXN], dep[MAXN]; char tpc[10]; int pos_tree[MAXN]; int num[MAXN]; void init() { memset(head, -1, sizeof head); cn_edge = 0; cn_tree = 0; top[0] = 0, siz[0] = 0, son[0] = 0; fa[0] = 0; dep[0] = 0; } void add(int u, int v) { edge[cn_edge].to = v; edge[cn_edge].next = head[u]; head[u] = cn_edge++; } void dfs1(int u, int pre) { fa[u] = pre; dep[u] = dep[pre] + 1; siz[u] = 1; son[u] = 0; for (int i = head[u]; ~i; i = edge[i].next) { int v = edge[i].to; if (v == pre) continue; dfs1(v, u); siz[u] += siz[v]; if (siz[son[u]] < siz[v]) son[u] = v; } } void dfs2(int u, int p) { top[u] = p; pos_tree[u] = ++cn_tree; if (!son[u]) return; dfs2(son[u], p); for (int i = head[u]; ~i; i = edge[i].next) { int v = edge[i].to; if ( v != fa[u] && v!=son[u]) dfs2(v, v); } } #define lr rot<<1 #define rr (rot<<1)|1 #define lson l,m,lr #define rson m+1,r,rr #define mid m=(l+r)>>1; int num_add[MAXN<<2]; void pushDOWN(int l, int r, int rot) { if (l == r) return; num_add[lr] += num_add[rot]; num_add[rr] += num_add[rot]; num_add[rot]= 0; } void build(int l, int r, int rot) { num_add[rot] = 0; if (l == r) return ; int mid; build(lson); build(rson); } void update(int L, int R, int val, int l, int r, int rot) { if ( L <= l && R >= r) { num_add[rot] += val; return; } pushDOWN(l,r,rot); int mid; if (L <= m ) update(L,R,val,lson); if (R > m) update(L,R,val,rson); } int query(int ps, int l, int r, int rot) { if ( l== r) return num_add[rot]; pushDOWN(l,r,rot); int mid; if (ps <= m) return query(ps, lson); else return query(ps, rson); } void solve(int a, int b, int k) { while (top[a] != top[b]) { if (dep[top[a]] < dep[top[b]]) swap(a, b); update(pos_tree[top[a]], pos_tree[a], k, 1, n, 1); a = fa[top[a]]; } if (dep[a] > dep[b]) swap(a, b); update(pos_tree[a], pos_tree[b], k, 1, n, 1); } int main() { #ifdef __GNUC__ freopen ( "in.txt", "r", stdin ); #endif // __GNUC__ while (scanf("%d%d%d", &n, &m, &q) != EOF) { init(); for (int i = 1; i<=n; ++i) scanf("%d", num+i); for (int i = 0; i< m; ++i) { int u, v; scanf("%d%d", &u, &v); add(u, v); add(v, u); } dfs1(1, 0); dfs2(1, 1); build(1,n,1); while (q--) { scanf("%s", tpc); if (tpc[0] == 'Q') { int val; scanf("%d", &val); printf("%d\n", num[val] + query(pos_tree[val], 1,n,1)); } else { int l, r, v; scanf("%d%d%d", &l, &r, &v); if (tpc[0] == 'D') v= -v; solve(l, r, v); } } } return 0; }