题意:树上进行两种操作:
(1)链上+d
(2)子树求和
直接链剖即可,子树求和就dfs序即可。
注意,dfs序按照重儿子在最先的序列,然后建立线段树。
1 /************************************************************** 2 Problem: 2836 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:4180 ms 7 Memory:20264 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <algorithm> 12 13 using namespace std; 14 typedef long long ll; 15 16 const int N = 100005; 17 18 struct edge { 19 int next, to; 20 edge() {} 21 edge(int _n, int _t) : next(_n), to(_t) {} 22 } e[N]; 23 24 struct tree_node { 25 int fa, son, sz, dep, st, ed, top; 26 } tr[N]; 27 28 struct seg_node { 29 seg_node *ls, *rs; 30 int len; 31 ll v, tag; 32 } *root, mempool[N << 2], *cnt_seg = mempool, *null; 33 34 int n, Q; 35 int first[N], tot, cnt_q; 36 37 int read() { 38 int x = 0; 39 char ch = getchar(); 40 while (ch < ‘0‘ || ‘9‘ < ch) 41 ch = getchar(); 42 while (‘0‘ <= ch && ch <= ‘9‘) 43 (x *= 10) += ch - ‘0‘, ch = getchar(); 44 return x; 45 } 46 47 inline void add_edge(int x, int y) { 48 e[++tot] = edge(first[x], y); 49 first[x] = tot; 50 } 51 52 #define y e[x].to 53 #define Son tr[p].son 54 void dfs(int p) { 55 int x; 56 tr[p].sz = 1; 57 for (x = first[p]; x; x = e[x].next) { 58 tr[y].dep = tr[p].dep + 1; 59 dfs(y); 60 tr[p].sz += tr[y].sz; 61 if (Son == 0 || tr[y].sz > tr[Son].sz) 62 Son = y; 63 } 64 } 65 66 void DFS(int p) { 67 int x; 68 tr[p].st = ++cnt_q; 69 if (Son) { 70 tr[Son].top = tr[p].top; 71 DFS(Son); 72 } 73 for (x = first[p]; x; x = e[x].next) 74 if (y != Son) { 75 tr[y].top = y; 76 DFS(y); 77 } 78 tr[p].ed = cnt_q; 79 } 80 #undef y 81 #undef Son 82 83 #define mid (l + r >> 1) 84 #define Ls p -> ls 85 #define Rs p -> rs 86 #define V p -> v 87 #define Tag p -> tag 88 #define Len p -> len 89 inline void push_tag(seg_node *p) { 90 Ls -> tag += Tag, Rs -> tag += Tag; 91 Ls -> v += 1ll * Tag * Ls -> len, Rs -> v += 1ll * Tag * Rs -> len; 92 Tag = 0; 93 } 94 95 inline void update(seg_node *p) { 96 V = Ls -> v + Rs -> v; 97 } 98 99 void seg_build(seg_node *&p, int l, int r) { 100 p = ++cnt_seg, Ls = Rs = null; 101 Len = r - l + 1; 102 V = Tag = 0; 103 if (l == r) return; 104 seg_build(Ls, l, mid), seg_build(Rs, mid + 1, r); 105 } 106 107 void seg_modify(seg_node *p, int l, int r, int L, int R, int d) { 108 if (l == L && R == r) { 109 Tag += d, V += 1ll * Len * d; 110 return; 111 } 112 push_tag(p); 113 if (L <= mid) seg_modify(Ls, l, mid, L, min(mid, R), d); 114 if (mid < R) seg_modify(Rs, mid + 1, r, max(mid + 1, L), R, d); 115 update(p); 116 } 117 118 ll seg_query(seg_node *p, int l, int r, int L, int R) { 119 if (l == L && R == r) 120 return V; 121 push_tag(p); 122 ll res = 0; 123 if (L <= mid) res += seg_query(Ls, l, mid, L, min(mid, R)); 124 if (mid < R) res += seg_query(Rs, mid + 1, r, max(mid + 1, L), R); 125 return res; 126 } 127 #undef mid 128 #undef Ls 129 #undef Rs 130 #undef V 131 #undef Tag 132 #undef Len 133 134 void work_add(int x, int y, int d) { 135 while (tr[x].top != tr[y].top) { 136 if (tr[tr[x].top].dep < tr[tr[y].top].dep) swap(x, y); 137 seg_modify(root, 1, n, tr[tr[x].top].st, tr[x].st, d); 138 x = tr[tr[x].top].fa; 139 } 140 if (tr[x].dep < tr[y].dep) swap(x, y); 141 seg_modify(root, 1, n, tr[y].st, tr[x].st, d); 142 } 143 144 int main() { 145 int i, x, y, d, oper; 146 null = cnt_seg; 147 null -> ls = null -> rs = null; 148 n = read(); 149 for (i = 1; i < n; ++i) { 150 x = read() + 1, y = read() + 1; 151 tr[y].fa = x; 152 add_edge(x, y); 153 } 154 dfs(1); 155 tr[1].top = 1; 156 DFS(1); 157 seg_build(root, 1, n); 158 Q = read(); 159 while (Q--) { 160 oper = getchar(); 161 while (oper != ‘A‘ && oper != ‘Q‘) oper = getchar(); 162 if (oper == ‘A‘) { 163 x = read() + 1, y = read() + 1, d = read(); 164 work_add(x, y, d); 165 } 166 else { 167 x = read() + 1; 168 printf("%lld\n", seg_query(root, 1, n, tr[x].st, tr[x].ed)); 169 } 170 } 171 return 0; 172 }
原文:http://www.cnblogs.com/rausen/p/4280574.html