#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef DEBUG #include "./Lib/debug.hpp" #else #define dump(...) templateinline auto d_val(T a, T b) { return a; } #endif /* (=^o^=) */ #define int ll /* macro */ #define FOR(i, b, e) for(ll i = (ll)(b); i < (ll)(e); ++i) #define RFOR(i, b, e) for(ll i = (ll)(e-1); i >= (ll)(b); --i) #define REP(i, n) FOR(i, 0, n) #define RREP(i, n) RFOR(i, 0, n) #define REPC(x,c) for(const auto& x:(c)) #define REPI2(it,b,e) for(auto it = (b); it != (e); ++it) #define REPI(it,c) REPI2(it, (c).begin(), (c).end()) #define RREPI(it,c) REPI2(it, (c).rbegin(), (c).rend()) #define REPI_ERACE2(it, b, e) for(auto it = (b); it != (e);) #define REPI_ERACE(it, c) REPI_ERACE2(it, (c).begin(), (c).end()) #define ALL(x) (x).begin(),(x).end() #define cauto const auto& /* macro func */ #define SORT(x) do{sort(ALL(x));}while(false) #define RSORT(x) do{sort((x).rbegin(),(x).rend());}while(false) #define UNIQUE(v) do{v.erase( unique(v.begin(), v.end()), v.end() );}while(false) #define MAX(x,y) do{x = std::max(x,y);}while(false) #define MIN(x,y) do{x = std::min(x,y);}while(false) #define BR do{cout<<"\n";}while(false) /* type define */ using ll = long long; using PAIR = std::pair; using VS = std::vector; using VL = std::vector; using VVL = std::vector; using VVVL = std::vector; using VD = std::vector; template using V = std::vector; /* using std */ using std::cout; constexpr char endl = '\n'; using std::cin; using std::sort; using std::pair; using std::string; using std::stack; using std::queue; using std::vector; using std::list; using std::map; using std::unordered_map; using std::multimap; using std::unordered_multimap; using std::set; using std::unordered_set; using std::unordered_multiset; using std::multiset; using std::bitset; using std::priority_queue; /* constant value */ constexpr ll MOD = 1000000007; //constexpr ll MOD = 998244353; /* Initial processing */ struct Preprocessing { Preprocessing() { std::cin.tie(0); std::ios::sync_with_stdio(0); }; }_Preprocessing; /* Remove the source of the bug */ signed pow(signed, signed) { assert(false); return -1; } /* define hash */ namespace std { template <> class hash> { public: size_t operator()(const std::pair& x) const { return hash()(1000000000 * x.first + x.second); } }; } /* input */ template std::istream& operator >> (std::istream& is, vector& vec) { for (T& x : vec) is >> x; return is; } //============================================================================================= /** * セグメント木を構成する * 2methodの変更により調整 */ template class SegmentTree { private: const T initialValue = 0; const T ignoreValue = 0; const ll m_size; vector m_node; ll calcSize(ll n) { ll size = 1; while (size < n) { size *= 2; } return size; } /** * 値の更新(更新:=, 加算:+=, etc...) */ void update(ll k, T x) { m_node[k] = x; } /** * 値の併合 */ T merge(T xl, T xr) { return xl + xr; } public: SegmentTree(ll n) : m_size(calcSize(n)), m_node(m_size * 2 - 1, initialValue) {} void add(ll itr, T val) { ll i = itr + m_size - 1; update(i, val); while (i > 0) { i = (i - 1) / 2; m_node[i] = merge(m_node[i * 2 + 1], m_node[i * 2 + 2]); } /** cout << "-- tree -- " << endl; REP(i, 2 * m_size - 1) { cout << m_node[i] << endl; } /*//**/ } T query(ll a, ll b) { return query(a, b + 1, 0, 0, m_size); } T query(ll a, ll b, ll k, ll l, ll r) { if (r <= a || b <= l) { return ignoreValue; } if (a <= l && r <= b) { return m_node[k]; } return merge( query(a, b, 2 * k + 1, l, (l + r) / 2), query(a, b, 2 * k + 2, (l + r) / 2, r) ); } }; class HLDecomposition { std::unordered_multimap m_graph; std::unordered_map m_graphRev; const int m_root; std::vector m_nodeList; std::vector m_nodeListPos; std::vector m_nodeCostList; std::vector> m_nodeRange; SegmentTree m_tree; static auto reverse(const std::unordered_multimap& graph) { std::unordered_map graphRev; for (const auto& p : graph) { graphRev.emplace(p.second, p.first); } return graphRev; } static auto getRoot(int size, const unordered_multimap& graph) { std::vector children(size, false); for (const auto& p : graph) { children[p.second] = true; } for (int i = 0; i < size; ++i)if (!children[i]) { return i; } } static auto getTreeSize(int size, const unordered_multimap& graph, int root) { auto treeSize = std::vector(size, 1); auto calcTreeSize = [&](auto f, auto from) { auto range = graph.equal_range(from); if (range.first == range.second) { return; } for (auto itr = range.first; itr != range.second; ++itr) { auto to = itr->second; f(f, to); treeSize[from] += treeSize[to]; } }; calcTreeSize(calcTreeSize, root); return treeSize; } auto decomposition(const unordered_multimap& graph, const std::vector& nodeCost, const std::vector& tSize, int now, int&& nodeFrom) { if (nodeFrom == -1) { nodeFrom = now; } m_nodeList.emplace_back(now); m_nodeCostList.emplace_back(nodeCost[now]); m_nodeListPos[now] = m_nodeList.size() - 1; m_nodeRange.emplace_back(m_nodeListPos[nodeFrom], -1); auto range = graph.equal_range(now); if (range.first == range.second) { for (int f = m_nodeListPos[nodeFrom]; f <= m_nodeListPos[now]; ++f) { m_nodeRange[f].second = m_nodeListPos[now]; } nodeFrom = -1; return; } auto large = -1; auto sMax = -1; for (auto itr = range.first; itr != range.second; ++itr) { auto to = itr->second; if (tSize[to] > sMax) { sMax = tSize[to]; large = to; } } decomposition(graph, nodeCost, tSize, large, std::forward(nodeFrom)); for (auto itr = range.first; itr != range.second; ++itr) { auto to = itr->second; if (to == large) { continue; } decomposition(graph, nodeCost, tSize, to, std::forward(nodeFrom)); } } auto construct(int size, const unordered_multimap& graph, const std::vector& nodeCost) { m_nodeList.reserve(size); m_nodeCostList.reserve(size); m_nodeRange.reserve(size); decomposition(graph, nodeCost, getTreeSize(size, graph, m_root), m_root, -1); } public: HLDecomposition(int size, const unordered_multimap& graph, const std::vector& nodeCost) : m_graph(graph), m_graphRev(reverse(m_graph)), m_root(getRoot(size, graph)), m_nodeListPos(size), m_tree(size) { construct(size, graph, nodeCost); for (int i = 0; i < size; ++i) { m_tree.add(i, m_nodeCostList[i]); } } HLDecomposition(int size, const unordered_multimap& graph) : m_graph(graph), m_graphRev(reverse(m_graph)), m_root(getRoot(size, graph)), m_nodeListPos(size), m_tree(size) { construct(size, graph, std::vector(size)); for (int i = 0; i < size; ++i) { m_tree.add(i, m_nodeCostList[i]); } } void debugOutput() const { dump(m_nodeList, m_nodeCostList, m_nodeRange); } /** * 最小共通祖先,LCA(Lowest Common Ancestor)を得る */ auto LCA(int a, int b) { while (a != b) { auto posa = m_nodeListPos[a]; auto posb = m_nodeListPos[b]; if (posa > posb) { std::swap(posa, posb); a = m_nodeList[posa]; } if (m_nodeRange[posb].first <= posa && posa <= m_nodeRange[posb].second) { b = a; break; } b = m_graphRev[m_nodeList[m_nodeRange[posb].first]]; } return a; } /** * セグ木を更新 *//**/ auto add(int itr, int x) { m_tree.add(itr, x); }/*/**/ /** * (遅延)セグ木から値を取得 */ auto query(int a, int b) { ll val = 0;//TODO: bool flg = false; while (a != b) { auto posa = m_nodeListPos[a]; auto posb = m_nodeListPos[b]; if (posa > posb) { std::swap(posa, posb); a = m_nodeList[posa]; } if (m_nodeRange[posb].first <= posa && posa <= m_nodeRange[posb].second) { val += m_tree.query(posa, posb); flg = true; b = a; break; } auto t = m_nodeRange[posb].first; val += m_tree.query(m_nodeRange[posb].first, posb); b = m_graphRev[m_nodeList[m_nodeRange[posb].first]]; } if (!flg) { val += m_tree.query(a, a); } return val; } }; signed main() { ll n; cin >> n; unordered_multimap graph_; REP(_, n - 1) { ll a, b; cin >> a >> b; graph_.emplace(a, b); graph_.emplace(b, a); } unordered_multimap graph; { V use(n); queue q; q.emplace(0); use[0] = true; while (!q.empty()) { ll from = q.front(); q.pop(); auto range = graph_.equal_range(from); REPI2(itr, range.first, range.second) { ll to = itr->second; if (!use[to]) { q.emplace(to); use[to] = true; graph.emplace(from, to); } } } } VL cost(n); cin >> cost; auto tree = HLDecomposition(n, graph, cost); ll q; cin >> q; ll ans = 0; REP(_, q) { ll a, b, c; cin >> a >> b >> c; ans += tree.query(a, b) * c; } cout << ans << endl; }