题意及题解
类似题目:CEOI2019 / CodeForces 1192B. Dynamic Diameter
线段树维护树的直径
const int MXN = 4e5 + 7;
const int MXE = 4e5 + 7;
typedef pair<int, LL> piL;
int n, m;
int fid[MXN], lid[MXN], rid[MXN], inde;
int fa[MXN], weight[MXN];
LL dis[MXN];
std::vector<piL > mp[MXN];
struct node {
int x, y;
LL z;
}edge[MXE];
void dfs_pre(int u, int ba) {
fid[u] = ++ inde;
rid[inde] = u;
for(auto V: mp[u]) {
int v = V.fi;
if(v == ba) continue;
fa[v] = u;
weight[v] = V.se;
dis[v] = dis[u] + V.se;
dfs_pre(v, u);
rid[++inde] = u;
}
lid[u] = inde;
}
struct lp {
LL val, lcav, LM, MR, LMR, lazy;
/*
len(a, b) = dis[a] + dis[b] - 2 * Min([a <= c <= b] dis[c])
线段树维护最大的len(a,b)即为直径。但是必须保证[a <= c <= b]
val = dis[x], lcav = -2 * dis[x]
LMR为直径
LM = val + lcav
MR = lcav + val
LMR = big(LM + val, val + MR)
*/
int p1, p2, p3, a, b;
friend lp operator + (const lp&lson, const lp&rson) {
lp rt;
rt.p1 = (lson.val >= rson.val ? lson.p1 : rson.p1);
rt.val = big(lson.val, rson.val);
rt.lcav = big(lson.lcav, rson.lcav);
if(lson.LM > rson.LM) rt.LM = lson.LM, rt.p2 = lson.p2;
else rt.LM = rson.LM, rt.p2 = rson.p2;
if(lson.MR > rson.MR) rt.MR = lson.MR, rt.p3 = lson.p3;
else rt.MR = rson.MR, rt.p3 = rson.p3;
if(lson.LMR > rson.LMR) rt.LMR = lson.LMR, rt.a = lson.a, rt.b = lson.b;
else rt.LMR = rson.LMR, rt.a = rson.a, rt.b = rson.b;
if(lson.val + rson.lcav > rt.LM) {
rt.LM = lson.val + rson.lcav;
rt.p2 = lson.p1;
}
if(lson.lcav + rson.val > rt.MR) {
rt.MR = lson.lcav + rson.val;
rt.p3 = rson.p1;
}
if(lson.LM + rson.val > rt.LMR) {
rt.LMR = lson.LM + rson.val;
rt.a = lson.p2, rt.b = rson.p1;
}
if(lson.val + rson.MR > rt.LMR) {
rt.LMR = lson.val + rson.MR;
rt.a = lson.p1, rt.b = rson.p3;
}
return rt;
}
}cw[MXN<<2];
#define lson rt << 1
#define rson rt << 1 | 1
void push_up(int rt) { cw[rt] = cw[lson] + cw[rson]; }
void build(int l, int r, int rt) {
if(l == r) {
int x = rid[l];
cw[rt].lazy = 0;
cw[rt].val = dis[x];
cw[rt].lcav = - (dis[x] + dis[x]);
cw[rt].LM = cw[rt].MR = - dis[x];
cw[rt].LMR = 0;
cw[rt].p1 = cw[rt].p2 = cw[rt].p3 = cw[rt].a = cw[rt].b = x;
return ;
}
int mid = (l + r) >> 1;
build(l, mid, rt << 1), build(mid + 1, r, rt << 1 | 1);
push_up(rt);
}
void push_down(int rt) {
if(cw[rt].lazy == 0) return ;
cw[lson].val += cw[rt].lazy;
cw[rson].val += cw[rt].lazy;
cw[lson].lcav -= cw[rt].lazy + cw[rt].lazy;
cw[rson].lcav -= cw[rt].lazy + cw[rt].lazy;
cw[lson].LM -= cw[rt].lazy;
cw[rson].LM -= cw[rt].lazy;
cw[lson].MR -= cw[rt].lazy;
cw[rson].MR -= cw[rt].lazy;
cw[lson].lazy += cw[rt].lazy;
cw[rson].lazy += cw[rt].lazy;
cw[rt].lazy = 0;
}
void update(int L, int R, LL v, int l, int r, int rt) {
if(L <= l && r <= R) {
cw[rt].val += v;
cw[rt].lcav -= v + v;
cw[rt].LM -= v;
cw[rt].MR -= v;
cw[rt].lazy += v;
return ;
}
int mid = (l + r) >> 1;
push_down(rt);
if(L > mid) update(L, R, v, mid + 1, r, rson);
else if(R <= mid) update(L, R, v, l, mid, lson);
else {
update(L, mid, v, l, mid, lson), update(mid + 1, R, v, mid + 1, r, rson);
}
push_up(rt);
}
LL query(int p, int l, int r, int rt) {
if(l == r) return cw[rt].val;
int mid = (l + r) >> 1;
push_down(rt);
if(p <= mid) return query(p, l, mid, lson);
else return query(p, mid + 1, r, rson);
}
#undef lson
#undef rson
namespace LCA {
int up[MXN][22], lens[MXN];
int cnt, dfn[MXN], en[MXN], LOG[MXN];
void dfs(int u, int ba) {
lens[u] = lens[ba] + 1;
dfn[++cnt] = u;
en[u] = cnt;
for(auto V: mp[u]) {
int v = V.fi;
if(v == ba) continue;
dfs(v, u);
dfn[++ cnt] = u;
}
}
inline int cmp(int u, int v) { return lens[u] < lens[v] ? u: v; }
void init() {
cnt = lens[0] = 0;
dfs(1, 0);
LOG[1] = 0;
for(int i = 2; i <= cnt; ++i) LOG[i] = LOG[i-1] + ((1<<(LOG[i-1]+1))==i);
for(int i = 1; i <= cnt; ++i) up[i][0] = dfn[i];
for(int j = 1; (1<<j) <= cnt; ++j)
for(int i = 1; i + (1<<j) -1 <= cnt; ++i)
up[i][j] = cmp(up[i][j-1], up[i+(1<<(j-1))][j-1]);
}
inline int lca(int x, int y) {
int l = en[x], r = en[y];
if(l > r) swap(l, r);
int k = LOG[r - l + 1];
return cmp(up[l][k], up[r-(1<<k)+1][k]);
}
}
LL Get(int a, int b, int c) {
return query(fid[a], 1, inde, 1) + query(fid[b], 1, inde, 1) - 2 * query(fid[c], 1, inde, 1);
}
int main() {
#ifndef ONLINE_JUDGE
freopen("E://ADpan//in.in", "r", stdin);
// freopen("E://ADpan//out.out", "w", stdout);
#endif
n = read();
for(int i = 1, a, b; i < n; ++i) {
LL c;
a = read(), b = read(), c = read();
mp[a].eb(mk(b, c)), mp[b].eb(mk(a, c));
edge[i] = {a, b, c};
assert(c <= 1000000000);
}
LCA::init();
dfs_pre(1, 0);
build(1, inde, 1);
m = read();
char opt[2];
int x;
LL y;
while(m --) {
scanf("%s", opt);
x = read();
if(opt[0] == 'C') {
y = read();
assert(y <= 1000000000);
int px = (fa[edge[x].x] == edge[x].y ? edge[x].x: edge[x].y);
update(fid[px], lid[px], y - edge[x].z, 1, inde, 1);
edge[x].z = y;
weight[px] = y;
}else {
int a = cw[1].a, b = cw[1].b;
int la = LCA::lca(a, x), lb = LCA::lca(b, x);
printf("%lld\n", big(Get(x, a, la), Get(x, b, lb)));
}
}
#ifndef ONLINE_JUDGE
cout << "time cost:" << 1.0*clock()/CLOCKS_PER_SEC << "ms" << endl;
#endif
return 0;
}