类似题目: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;
}
const int MXN = 1e5 + 7;
const int MXE = 1e5 + 7;
typedef pair<int, LL> piL;
int n, m;
int fa[MXN], vis[MXN], sz[MXN], points, hvy, hvysiz, inde, dis[MXN];
unordered_map<int, int> fid[MXN], lid[MXN], whichson[MXN], bel[MXN];
std::vector<piL > mp[MXN];
struct LP {
LL len;
int x, y;
bool operator <(const LP&b) const {
if(len != b.len) return len < b.len;
if(x != b.x) return x < b.x;
return y < b.y;
}
};
multiset<LP> ans;
struct node {
int x, y;
LL z;
}edge[MXE];
namespace LCA {
int up[MXN * 2][22], lens[MXN];
int cnt, dfn[MXN * 2], en[MXN], LOG[MXN * 2], inde, fid[MXN], lid[MXN], to[MXN];
LL bit[MXN], dep[MXN];
void bit_add(int x, LL v) {
while(x <= n) {
bit[x] += v;
x += lowbit(x);
}
}
LL bit_qry(int x) {
x = fid[x];
LL res = 0;
while(x > 0) {
res += bit[x];
x -= lowbit(x);
}
return res;
}
void dfs(int u, int ba) {
lens[u] = lens[ba] + 1;
dfn[++cnt] = u;
en[u] = cnt;
fid[u] = ++ inde;
to[inde] = u;
for(auto V: mp[u]) {
int v = V.fi;
if(v == ba) continue;
dep[v] = dep[u] + V.se;
dfs(v, u);
dfn[++ cnt] = u;
}
lid[u] = inde;
}
inline int cmp(int u, int v) { return lens[u] < lens[v] ? u: v; }
void init() {
inde = cnt = lens[0] = 0;
dfs(1, -1);
dep[0] = to[0] = 0;
for(int i = 1; i <= n; ++i) bit_add(i, dep[to[i]] - dep[to[i-1]]);
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]);
}
}
struct Seg {
std::vector<LL> sum, lazy;
std::vector<int> is;
multiset<LP> ms;
void build(int l, int r, int rt) {
if(l == r) {
is[rt] = l;
return;
}
int mid = (l + r) >> 1;
build(l, mid, rt << 1), build(mid + 1, r, rt << 1 | 1);
push_up(rt);
}
void resize(int _n) {
sum.clear(), lazy.clear(), is.clear();
sum.shrink_to_fit(), lazy.shrink_to_fit(), is.shrink_to_fit();
sum.resize(4 * _n + 1), lazy.resize(4 * _n + 1), is.resize(4 * _n + 1);
build(1, _n, 1);
// debug(4 * _n)
// for(int i = 0; i <= 4 * _n; ++i) assert(sum[i] == 0 && lazy[i] == 0);
}
void push_down(int rt) {
if(!lazy[rt]) return ;
lazy[rt << 1] += lazy[rt];
lazy[rt << 1 | 1] += lazy[rt];
sum[rt << 1] += lazy[rt];
sum[rt << 1 | 1] += lazy[rt];
lazy[rt] = 0;
}
void push_up(int rt) {
if(sum[rt << 1] > sum[rt << 1 | 1]) {
sum[rt] = sum[rt << 1];
is[rt] = is[rt << 1];
}else {
sum[rt] = sum[rt << 1 | 1];
is[rt] = is[rt << 1 | 1];
}
}
void update(int L, int R, LL v, int l, int r, int rt) {
if(L <= l && r <= R) {
sum[rt] += v;
lazy[rt] += v;
return ;
}
int mid = (l + r) >> 1;
push_down(rt);
if(L > mid) update(L, R, v, mid + 1, r, rt << 1 | 1);
else if(R <= mid) update(L, R, v, l, mid, rt << 1);
else {
update(L, mid, v, l, mid, rt << 1), update(mid + 1, R, v, mid + 1, r, rt << 1 | 1);
}
push_up(rt);
}
piL query(int L, int R, int l, int r, int rt) {
if(L <= l && r <= R) return mk(is[rt], sum[rt]);
int mid = (l + r) >> 1;
push_down(rt);
if(L > mid) return query(L, R, mid + 1, r, rt << 1 | 1);
else if(R <= mid) return query(L, R, l, mid, rt << 1);
piL a = query(L, mid, l, mid, rt << 1);
piL b = query(mid + 1, R, mid + 1, r, rt << 1 | 1);
return a.se > b.se ? a: b;
}
LP getans() {
if((int)ms.size() == 1) return *ms.begin();
else {
LP a;
auto it = ms.end();
-- it;
a.len = (*it).len;
a.x = (*it).y;
-- it;
a.len += (*it).len;
a.y = (*it).y;
return a;
}
}
}seg[MXN];
void dfs_pre(int u, int ba) {
sz[u] = 1;
int mm = 0;
for(auto V: mp[u]) {
int v = V.fi;
if(v == ba || vis[v]) continue;
fa[v] = u;
dfs_pre(v, u);
sz[u] += sz[v];
mm = big(sz[v], mm);
}
mm = big(points - sz[u], mm);
if(hvy == -1 || mm < hvysiz) hvy = u, hvysiz = mm;
}
void dfs_sz(int u, int ba) {sz[u] = 1;for(auto V: mp[u]) {int v = V.fi;if(v == ba || vis[v]) continue;dfs_sz(v, u);sz[u] += sz[v];}}
void build_tree(int u, int ba, LL lst, int rt, int x) {
fid[rt][u] = ++ inde;
whichson[rt][inde] = u;
if(x != -1) bel[rt][u] = x;
for(auto V: mp[u]) {
if(vis[V.fi] || V.fi == ba) continue;
build_tree(V.fi, u, V.se, rt, x == -1?V.fi:x);
}
lid[rt][u] = inde;
// debug(fid[rt][u], lid[rt][u], sz[rt])
if(lst) seg[rt].update(fid[rt][u], lid[rt][u], lst, 1, sz[rt], 1);
}
void build_segtree(int u) {
inde = 0;
dfs_sz(u, 0);
seg[u].resize(sz[u]);
build_tree(u, 0, 0, u, -1);
for(auto V: mp[u]) {
if(vis[V.fi]) continue;
piL a = seg[u].query(fid[u][V.fi], lid[u][V.fi], 1, lid[u][u], 1);
seg[u].ms.insert({a.se, u, whichson[u][a.fi]});
}
if((int)seg[u].ms.size()) ans.insert(seg[u].getans());
}
void dfs_fz(int st, int ba) {
hvy = hvysiz = -1;
dfs_pre(st, 0);
int u = hvy;
fa[u] = ba;
vis[u] = 1;
dis[u] = dis[ba] + 1;
build_segtree(u);
for(auto V: mp[u]) {
if(vis[V.fi] || V.fi == ba) continue;
points = sz[V.fi];
dfs_fz(V.fi, u);
}
}
int main() {
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};
}
LCA::init();
points = n;
dfs_fz(1, 0);
m = read();
char opt[2];
int x;
LL y;
while(m --) {
scanf("%s", opt);
x = read();
if(opt[0] == 'C') {
y = read();
LL ty = y;
y -= edge[x].z;
int px = edge[x].x, py = edge[x].y;
if(dis[px] > dis[py]) swap(px, py);
int tmp = px;
piL res;
LP lp1;
// debug(tmp, px, py, y, edge[x].z)
while(tmp) {
// debug(tmp)
if((int)seg[tmp].ms.size()) {
lp1 = seg[tmp].getans();
auto IT = ans.lower_bound(lp1);
ans.erase(IT);
}
int ret = fid[tmp][px] < fid[tmp][py] ? py : px;
res = seg[tmp].query(fid[tmp][bel[tmp][ret]], lid[tmp][bel[tmp][ret]], 1, lid[tmp][tmp], 1);
// debug(tmp, fid[tmp][ret], lid[tmp][ret], res.se, whichson[tmp][res.fi])
auto it = seg[tmp].ms.lower_bound({res.se, tmp, whichson[tmp][res.fi]});
// debug((*it).len, (*it).x, (*it).y)
seg[tmp].ms.erase(it);
seg[tmp].update(fid[tmp][ret], lid[tmp][ret], y, 1, lid[tmp][tmp], 1);
res = seg[tmp].query(fid[tmp][bel[tmp][ret]], lid[tmp][bel[tmp][ret]], 1, lid[tmp][tmp], 1);
// debug(tmp, fid[tmp][ret], lid[tmp][ret], res.se, whichson[tmp][res.fi])
seg[tmp].ms.insert({res.se, tmp, whichson[tmp][res.fi]});
if((int)seg[tmp].ms.size()) ans.insert(seg[tmp].getans());
tmp = fa[tmp];
}
// debug(edge[x].z, ty, y)
edge[x].z = ty;
if(LCA::lens[px] > LCA::lens[py]) swap(px, py);
LCA::bit_add(LCA::fid[py], y);
LCA::bit_add(LCA::lid[py] + 1, -y);
}else {
auto it = ans.end();
-- it;
int a = (*it).x, b = (*it).y;
int la = LCA::lca(a, x), lb = LCA::lca(b, x);
printf("%lld\n", LCA::bit_qry(x) + big(LCA::bit_qry(a) - LCA::bit_qry(la) * 2, LCA::bit_qry(b) - LCA::bit_qry(lb) * 2));
}
}
return 0;
}