// start A.cpp // #pragma GCC target("avx2") // #pragma GCC optimize("O3") // #pragma GCC optimize("unroll-loops") #include using namespace std; using ll = long long; using ull = unsigned long long; template using pq = priority_queue; template using qp = priority_queue, greater>; #define vec(T, A, ...) vector A(__VA_ARGS__); #define vvec(T, A, h, ...) vector> A(h, vector(__VA_ARGS__)); #define vvvec(T, A, h1, h2, ...) vector>> A(h1, vector>(h2, vector(__VA_ARGS__))); #ifndef RIN__LOCAL #define endl "\n" #endif #define spa ' ' #define len(A) A.size() #define all(A) begin(A), end(A) #define fori1(a) for (ll _ = 0; _ < (a); _++) #define fori2(i, a) for (ll i = 0; i < (a); i++) #define fori3(i, a, b) for (ll i = (a); i < (b); i++) #define fori4(i, a, b, c) for (ll i = (a); ((c) > 0 || i > (b)) && ((c) < 0 || i < (b)); i += (c)) #define overload4(a, b, c, d, e, ...) e #define fori(...) overload4(__VA_ARGS__, fori4, fori3, fori2, fori1)(__VA_ARGS__) vector stoc(string &S) { int n = S.size(); vector ret(n); for (int i = 0; i < n; i++) ret[i] = S[i]; return ret; } #define INT(...) \ int __VA_ARGS__; \ inp(__VA_ARGS__); #define LL(...) \ ll __VA_ARGS__; \ inp(__VA_ARGS__); #define STRING(...) \ string __VA_ARGS__; \ inp(__VA_ARGS__); #define CHAR(...) \ char __VA_ARGS__; \ inp(__VA_ARGS__); #define VEC(T, A, n) \ vector A(n); \ inp(A); #define VVEC(T, A, n, m) \ vector> A(n, vector(m)); \ inp(A); const ll MOD1 = 1000000007; const ll MOD9 = 998244353; template auto min(const T &a) { return *min_element(all(a)); } template auto max(const T &a) { return *max_element(all(a)); } template auto clamp(T &a, const S &l, const S &r) { return (a > r ? r : a < l ? l : a); } template inline bool chmax(T &a, const S &b) { return (a < b ? a = b, 1 : 0); } template inline bool chmin(T &a, const S &b) { return (a > b ? a = b, 1 : 0); } template inline bool chclamp(T &a, const S &l, const S &r) { auto b = clamp(a, l, r); return (a != b ? a = b, 1 : 0); } void FLUSH() { cout << flush; } void print() { cout << endl; } template void print(Head &&head, Tail &&...tail) { cout << head; if (sizeof...(Tail)) cout << spa; print(forward(tail)...); } template void print(vector &A) { int n = A.size(); for (int i = 0; i < n; i++) { cout << A[i]; if (i != n - 1) cout << ' '; } cout << endl; } template void print(vector> &A) { for (auto &row : A) print(row); } template void print(pair &A) { cout << A.first << spa << A.second << endl; } template void print(vector> &A) { for (auto &row : A) print(row); } template void prisep(vector &A, S sep) { int n = A.size(); for (int i = 0; i < n; i++) { cout << A[i]; if (i != n - 1) cout << sep; } cout << endl; } template void priend(T A, S end) { cout << A << end; } template void priend(T A) { priend(A, spa); } template bool printif(bool f, T A, S B) { if (f) print(A); else print(B); return f; } template void inp(T &...a) { (cin >> ... >> a); } template void inp(vector &A) { for (auto &a : A) cin >> a; } template void inp(vector> &A) { for (auto &row : A) inp(row); } template void inp(pair &A) { inp(A.first, A.second); } template void inp(vector> &A) { for (auto &row : A) inp(row.first, row.second); } template T sum(vector &A) { T tot = 0; for (auto a : A) tot += a; return tot; } template vector compression(vector X) { sort(all(X)); X.erase(unique(all(X)), X.end()); return X; } vector> read_edges(int n, int m, bool direct = false, int indexed = 1) { vector> edges(n, vector()); for (int i = 0; i < m; i++) { INT(u, v); u -= indexed; v -= indexed; edges[u].push_back(v); if (!direct) edges[v].push_back(u); } return edges; } vector> read_tree(int n, int indexed = 1) { return read_edges(n, n - 1, false, indexed); } template vector>> read_wedges(int n, int m, bool direct = false, int indexed = 1) { vector>> edges(n, vector>()); for (int i = 0; i < m; i++) { INT(u, v); T w; inp(w); u -= indexed; v -= indexed; edges[u].push_back({v, w}); if (!direct) edges[v].push_back({u, w}); } return edges; } template vector>> read_wtree(int n, int indexed = 1) { return read_wedges(n, n - 1, false, indexed); } inline bool yes(bool f = true) { cout << (f ? "yes" : "no") << endl; return f; } inline bool Yes(bool f = true) { cout << (f ? "Yes" : "No") << endl; return f; } inline bool YES(bool f = true) { cout << (f ? "YES" : "NO") << endl; return f; } inline bool no(bool f = true) { cout << (!f ? "yes" : "no") << endl; return f; } inline bool No(bool f = true) { cout << (!f ? "Yes" : "No") << endl; return f; } inline bool NO(bool f = true) { cout << (!f ? "YES" : "NO") << endl; return f; } // start atcoder/lazysegtree.hpp #ifndef ATCODER_LAZYSEGTREE_HPP #define ATCODER_LAZYSEGTREE_HPP 1 #include #include #include #include // start atcoder/internal_bit.hpp #ifndef ATCODER_INTERNAL_BITOP_HPP #define ATCODER_INTERNAL_BITOP_HPP 1 #ifdef _MSC_VER #include #endif namespace atcoder { namespace internal { // @param n `0 <= n` // @return minimum non-negative `x` s.t. `n <= 2**x` int ceil_pow2(int n) { int x = 0; while ((1U << x) < (unsigned int)(n)) x++; return x; } // @param n `1 <= n` // @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0` constexpr int bsf_constexpr(unsigned int n) { int x = 0; while (!(n & (1 << x))) x++; return x; } // @param n `1 <= n` // @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0` int bsf(unsigned int n) { #ifdef _MSC_VER unsigned long index; _BitScanForward(&index, n); return index; #else return __builtin_ctz(n); #endif } } // namespace internal } // namespace atcoder #endif // ATCODER_INTERNAL_BITOP_HPP // end atcoder/internal_bit.hpp // restart atcoder/lazysegtree.hpp namespace atcoder { template struct lazy_segtree { public: lazy_segtree() : lazy_segtree(0) {} explicit lazy_segtree(int n) : lazy_segtree(std::vector(n, e())) {} explicit lazy_segtree(const std::vector &v) : _n(int(v.size())) { log = internal::ceil_pow2(_n); size = 1 << log; d = std::vector(2 * size, e()); lz = std::vector(size, id()); for (int i = 0; i < _n; i++) d[size + i] = v[i]; for (int i = size - 1; i >= 1; i--) { update(i); } } void set(int p, S x) { assert(0 <= p && p < _n); p += size; for (int i = log; i >= 1; i--) push(p >> i); d[p] = x; for (int i = 1; i <= log; i++) update(p >> i); } S get(int p) { assert(0 <= p && p < _n); p += size; for (int i = log; i >= 1; i--) push(p >> i); return d[p]; } S prod(int l, int r) { assert(0 <= l && l <= r && r <= _n); if (l == r) return e(); l += size; r += size; for (int i = log; i >= 1; i--) { if (((l >> i) << i) != l) push(l >> i); if (((r >> i) << i) != r) push((r - 1) >> i); } S sml = e(), smr = e(); while (l < r) { if (l & 1) sml = op(sml, d[l++]); if (r & 1) smr = op(d[--r], smr); l >>= 1; r >>= 1; } return op(sml, smr); } S all_prod() { return d[1]; } void apply(int p, F f) { assert(0 <= p && p < _n); p += size; for (int i = log; i >= 1; i--) push(p >> i); d[p] = mapping(f, d[p]); for (int i = 1; i <= log; i++) update(p >> i); } void apply(int l, int r, F f) { assert(0 <= l && l <= r && r <= _n); if (l == r) return; l += size; r += size; for (int i = log; i >= 1; i--) { if (((l >> i) << i) != l) push(l >> i); if (((r >> i) << i) != r) push((r - 1) >> i); } { int l2 = l, r2 = r; while (l < r) { if (l & 1) all_apply(l++, f); if (r & 1) all_apply(--r, f); l >>= 1; r >>= 1; } l = l2; r = r2; } for (int i = 1; i <= log; i++) { if (((l >> i) << i) != l) update(l >> i); if (((r >> i) << i) != r) update((r - 1) >> i); } } template int max_right(int l) { return max_right(l, [](S x) { return g(x); }); } template int max_right(int l, G g) { assert(0 <= l && l <= _n); assert(g(e())); if (l == _n) return _n; l += size; for (int i = log; i >= 1; i--) push(l >> i); S sm = e(); do { while (l % 2 == 0) l >>= 1; if (!g(op(sm, d[l]))) { while (l < size) { push(l); l = (2 * l); if (g(op(sm, d[l]))) { sm = op(sm, d[l]); l++; } } return l - size; } sm = op(sm, d[l]); l++; } while ((l & -l) != l); return _n; } template int min_left(int r) { return min_left(r, [](S x) { return g(x); }); } template int min_left(int r, G g) { assert(0 <= r && r <= _n); assert(g(e())); if (r == 0) return 0; r += size; for (int i = log; i >= 1; i--) push((r - 1) >> i); S sm = e(); do { r--; while (r > 1 && (r % 2)) r >>= 1; if (!g(op(d[r], sm))) { while (r < size) { push(r); r = (2 * r + 1); if (g(op(d[r], sm))) { sm = op(d[r], sm); r--; } } return r + 1 - size; } sm = op(d[r], sm); } while ((r & -r) != r); return 0; } private: int _n, size, log; std::vector d; std::vector lz; void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); } void all_apply(int k, F f) { d[k] = mapping(f, d[k]); if (k < size) lz[k] = composition(f, lz[k]); } void push(int k) { all_apply(2 * k, lz[k]); all_apply(2 * k + 1, lz[k]); lz[k] = id(); } }; } // namespace atcoder #endif // ATCODER_LAZYSEGTREE_HPP // end atcoder/lazysegtree.hpp // restart A.cpp // start tree/HLD.hpp struct HLD { int n, path; vector> edges; vector siz; vector par; vector depth; vector path_ind; vector path_root; vector heavy_child; vector isheavy; vector L; vector R; HLD(int n) : n(n) { edges.resize(n); siz.assign(n, -1); par.assign(n, -1); depth.assign(n, -1); path_ind.assign(n, -1); heavy_child.assign(n, -1); isheavy.assign(n, false); L.assign(n, -1); R.assign(n, -1); } void read_edges(int indexed = 1) { int u, v; for (int i = 0; i < n - 1; i++) { cin >> u >> v; u -= indexed; v -= indexed; edges[u].push_back(v); edges[v].push_back(u); } } void add_edge(int u, int v) { edges[u].push_back(v); edges[v].push_back(u); } void build(int root = 0) { depth[root] = 0; stack st; vector route; st.push(root); route.push_back(root); while (!st.empty()) { int pos = st.top(); st.pop(); for (auto npos : edges[pos]) { if (depth[npos] == -1) { depth[npos] = depth[pos] + 1; par[npos] = pos; st.push(npos); route.push_back(npos); } } } reverse(route.begin(), route.end()); for (auto pos : route) { siz[pos] = 1; int ma = -1; for (auto npos : edges[pos]) { if (depth[npos] > depth[pos]) siz[pos] += siz[npos]; if (siz[npos] > ma) { ma = siz[npos]; heavy_child[pos] = npos; } } if (heavy_child[pos] != -1) isheavy[heavy_child[pos]] = true; } isheavy[root] = true; path = 0; st.push(~root); st.push(root); path_root.push_back(root); int cc = 0; while (!st.empty()) { int pos = st.top(); st.pop(); if (pos >= 0) { L[pos] = cc++; if (!isheavy[pos]) { path++; path_root.push_back(pos); } path_ind[pos] = path; for (auto npos : edges[pos]) { if (npos == par[pos] || npos == heavy_child[pos]) continue; st.push(~npos); st.push(npos); } if (heavy_child[pos] != -1) { int npos = heavy_child[pos]; st.push(~npos); st.push(npos); } } else { pos = ~pos; R[pos] = cc; } } } vector> get_path(int u, int v) { vector ll; vector rr; ll.push_back(u); rr.push_back(v); while (path_ind[u] != path_ind[v]) { if (depth[path_root[path_ind[u]]] >= depth[path_root[path_ind[v]]]) { u = path_root[path_ind[u]]; ll.push_back(u); u = par[u]; ll.push_back(u); } else { v = path_root[path_ind[v]]; rr.push_back(v); v = par[v]; rr.push_back(v); } } reverse(rr.begin(), rr.end()); ll.insert(ll.end(), rr.begin(), rr.end()); int n = ll.size(); vector> res(n / 2); for (int i = 0; i < n; i += 2) { res[i / 2] = {ll[i], ll[i + 1]}; } return res; } int lca(int u, int v) { while (path_ind[u] != path_ind[v]) { if (depth[path_root[path_ind[u]]] >= depth[path_root[path_ind[v]]]) u = par[path_root[path_ind[u]]]; else v = par[path_root[path_ind[v]]]; } return (depth[u] <= depth[v]) ? u : v; } int dist(int u, int v) { int p = lca(u, v); return depth[u] + depth[v] - 2 * depth[p]; } template vector reorder(vector &A, bool rev = false) { assert(n == A.size()); vector ret(n); for (int i = 0; i < n; i++) { ret[L[i]] = A[i]; } if (rev) reverse(ret.begin(), ret.end()); return ret; } }; // end tree/HLD.hpp // restart A.cpp const ll inf = 1LL << 60; ll op(ll l, ll r) { return l < r ? l : r; } ll e() { return inf; } ll mapping(ll f, ll x) { return f + x; } ll composition(ll f, ll g) { return f + g; } ll id() { return 0; } void solve() { INT(n); STRING(S); int g = 0; int b = 0; for (auto s : S) { if (s == 'G') g++; else b++; } if (g > b) { swap(g, b); fori(i, n) { S[i] = S[i] ^ 'B' ^ 'G'; } } if (g == 0) { fori(n - 1) { INT(u, v, w); } INT(Q); fori(Q) { INT(e, a); print(0); } return; } VVEC(ll, E, n - 1, 3); using P = pair; vvec(P, edges, n); for (auto &tmp : E) { tmp[0]--; tmp[1]--; edges[tmp[0]].emplace_back(tmp[1], tmp[2]); edges[tmp[1]].emplace_back(tmp[0], tmp[2]); } int cent = -1; vec(int, siz, n, 1); vec(int, gc, n, 0); auto dfs = [&](auto &&self, int pos, int bpos) -> void { bool ok = true; siz[pos] = 1; gc[pos] = 0; if (S[pos] == 'G') gc[pos]++; for (auto [npos, _] : edges[pos]) { if (npos == bpos) continue; self(self, npos, pos); siz[pos] += siz[npos]; gc[pos] += gc[npos]; if (siz[npos] * 2 > n) ok = false; } if ((n - siz[pos]) * 2 > n) ok = false; if (ok) cent = pos; }; dfs(dfs, 0, -1); HLD hld(n); for (auto tmp : E) hld.add_edge(tmp[0], tmp[1]); int cc = cent; hld.build(cent); dfs(dfs, cent, -1); cent = cc; vec(ll, ini, n, 0); fori(i, n) { if (siz[i] != g) ini[hld.L[i]] = inf; } atcoder::lazy_segtree seg(ini); vec(int, upp, n, -1); stack st; st.push(cent); upp[cent] = cent; while (!st.empty()) { int pos = st.top(); st.pop(); for (auto [npos, _] : edges[pos]) { if (upp[npos] == -1) { upp[npos] = upp[pos]; if (siz[pos] > g) upp[npos] = npos; st.push(npos); } } } auto add = [&](int u, int v, ll w) { if (hld.depth[u] < hld.depth[v]) swap(u, v); ll x = w * gc[u]; seg.apply(0, n, x); x *= -1; x += w * min(g - gc[u], siz[u] - gc[u]); u = upp[u]; seg.apply(hld.L[u], hld.R[u], x); }; for (auto tmp : E) { add(tmp[0], tmp[1], tmp[2]); } INT(Q); fori(Q) { LL(e, a); e--; add(E[e][0], E[e][1], a); print(seg.all_prod()); } } int main() { cin.tie(0)->sync_with_stdio(0); // cout << fixed << setprecision(12); int t; t = 1; // cin >> t; while (t--) solve(); return 0; } // end A.cpp