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;
}