LCA+树状数组,用由于dfs序列中同一子树节点是连续的,所以可以用树状数组维护dfs序列到到根的距离。
LCA都忘记咋写了,越来越依赖模板了~~
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <queue> #include <algorithm> #include <vector> #include <cstring> #include <stack> #include <cctype> #include <utility> #include <map> #include <string> #include <climits> #include <set> #include <string> #include <sstream> #include <utility> #include <ctime> using std::priority_queue; using std::vector; using std::swap; using std::stack; using std::sort; using std::max; using std::min; using std::pair; using std::map; using std::string; using std::cin; using std::cout; using std::set; using std::queue; using std::string; using std::istringstream; using std::make_pair; using std::getline; using std::greater; using std::endl; using std::multimap; using std::deque; typedef long long LL; typedef unsigned long long ULL; typedef pair<int, int> PAIR; typedef multimap<int, int> MMAP; const int MAXN(100010); const int SIGMA_SIZE(26); const int MAXM(110); const int MAXE(200010); const int MAXH(19); const int INFI((INT_MAX-1) >> 1); const int MOD(2012); const ULL BASE(31); const ULL LIM(1000000000000000ull); struct EDGE { int v, w, next; }; int first[MAXN]; EDGE edge[MAXE]; int rear; void init(int tn) { memset(first, -1, sizeof(first[0])*(tn+1)); rear = 0; } void insert(int tu, int tv, int tw) { edge[rear].v = tv; edge[rear].w = tw; edge[rear].next = first[tu]; first[tu] = rear++; } int sumdist[MAXN]; int ind; int poss[MAXN], pose[MAXN]; struct LCA { int E[MAXN << 1], dep[MAXN << 1], pos[MAXN]; int back; int table[MAXH][MAXN << 1]; inline int comp(int op1, int op2) { return dep[op1] <= dep[op2]? op1: op2; } void init() { back = 0; ind = 0; dfs(1, 0, 0, -1); for(int i = 1; i <= back; ++i) table[0][i] = i; for(int i = 1; (1 << i) <= back; ++i) for(int j = 1; j+(1 << i)-1 <= back; ++j) table[i][j] = comp(table[i-1][j], table[i-1][j+(1 << (i-1))]); } void dfs(int cur, int d, int dis, int tf) { E[++back] = cur; dep[back] = d; pos[cur] = back; sumdist[cur] = dis; poss[cur] = ++ind; for(int i = first[cur]; ~i; i = edge[i].next) if(edge[i].v != tf) { dfs(edge[i].v, d+1, dis+edge[i].w, cur); E[++back] = cur; dep[back] = d; } pose[cur] = ind; } int query(int op1, int op2) { op1 = pos[op1]; op2 = pos[op2]; if(op1 > op2) swap(op1, op2); int len = op2-op1+1, temp = 0; while((1 << temp) <= len) ++temp; --temp; return E[comp(table[temp][op1], table[temp][op2-(1 << temp)+1])]; } }; LCA lca; struct FENWICK_TREE { int table[MAXN]; int size; void init(int tn) { size = tn; memset(table+1, 0, sizeof(table[0])*tn); } inline int lowb(int op) { return op&(-op); } int query(int op) { int ret = 0; for(int i = op; i >= 1; i -= lowb(i)) ret += table[i]; return ret; } void add(int op, int value) { for(int i = op; i <= size; i += lowb(i)) table[i] += value; } }; FENWICK_TREE ft; int rec[3][MAXN]; int main() { int n, q, s; while(~scanf("%d%d%d", &n, &q, &s)) { int tu, tv, tw; init(n+1); for(int i = 1; i < n; ++i) { scanf("%d%d%d", &tu, &tv, &tw); insert(tu, tv, tw); insert(tv, tu, tw); rec[0][i] = tu; rec[1][i] = tv; rec[2][i] = tw; } lca.init(); ft.init(n); for(int i = 1; i <= n; ++i) { ft.add(poss[i], sumdist[i]); ft.add(poss[i]+1, -sumdist[i]); } int op1, op2, op3; for(int i = 0; i < q; ++i) { scanf("%d", &op1); if(op1) { scanf("%d%d", &op2, &op3); int ind = lca.dep[lca.pos[rec[0][op2]]] > lca.dep[lca.pos[rec[1][op2]]]? rec[0][op2]: rec[1][op2]; int dif = op3-rec[2][op2]; rec[2][op2] = op3; ft.add(poss[ind], dif); ft.add(pose[ind]+1, -dif); } else { scanf("%d", &op2); int ans = ft.query(poss[s])+ft.query(poss[op2])-2*ft.query(poss[lca.query(s, op2)]); s = op2; printf("%d\n", ans); } } } return 0; }