Archives
Trending
Support
Login
clear text
XML
Django
JavaScript
MATLAB
C
C++
C#
Python
SQL
Shell
Bash
Markdown
YAML
JSON
HTML
CSS
PHP
Java
Ruby
Go
Rust
Swift
Kotlin
Arduino
TypeScript
Perl
Autohotkey
Lua
SQF
R
Scala
Haskell
Groovy
Dart
Clojure
VB.NET
Objective-C
PowerShell
Bash
CoffeeScript
Verilog
#include
using namespace std; /** * Segment Tree supporting: * - Range increment updates * - Point queries */ class SegmentTree { vector
tree, lazy; int size; public: explicit SegmentTree(int n) : size(n) { tree.assign(4 * n + 5, 0); lazy.assign(4 * n + 5, 0); } // Build the tree from a given array void build(int idx, int left, int right, const vector
& values) { if (left == right) { tree[idx] = values[left]; return; } int mid = (left + right) / 2; build(idx * 2, left, mid, values); build(idx * 2 + 1, mid + 1, right, values); } // Lazy range update void update(int idx, int ql, int qr, int left, int right, long long val) { if (qr < left || ql > right) return; if (ql <= left && right <= qr) { lazy[idx] += val; return; } int mid = (left + right) / 2; update(idx * 2, ql, qr, left, mid, val); update(idx * 2 + 1, ql, qr, mid + 1, right, val); } // Point query: propagate laziness as we go down long long query(int idx, int pos, int left, int right) { if (pos < left || pos > right) return 0; if (left == right) { tree[idx] += lazy[idx]; lazy[idx] = 0; return tree[idx]; } // push lazy value to children lazy[idx * 2] += lazy[idx]; lazy[idx * 2 + 1] += lazy[idx]; lazy[idx] = 0; int mid = (left + right) / 2; if (pos <= mid) return query(idx * 2, pos, left, mid); else return query(idx * 2 + 1, pos, mid + 1, right); } }; // Global timer for Euler tour int timer = 1; /** * DFS to compute: * - timeIn/timeOut for each node * - prefix sum (sumToRoot) * - binary lifting table */ void dfs(int node, int parent, const vector
>>& graph, vector
& timeIn, vector
& timeOut, vector
& sumToRoot, vector
>& up) { timeIn[node] = timer++; for (auto [child, weight] : graph[node]) { if (child == parent) continue; up[child][0] = node; sumToRoot[child] = sumToRoot[node] + weight; dfs(child, node, graph, timeIn, timeOut, sumToRoot, up); } timeOut[node] = timer; } /** Checks if 'a' is an ancestor of 'b' */ bool isAncestor(int a, int b, const vector
& timeIn, const vector
& timeOut) { return timeIn[a] <= timeIn[b] && timeOut[a] >= timeOut[b]; } /** Compute Lowest Common Ancestor (LCA) using binary lifting */ int findLCA(int u, int v, const vector
>& up, const vector
& timeIn, const vector
& timeOut) { if (isAncestor(u, v, timeIn, timeOut)) return u; if (isAncestor(v, u, timeIn, timeOut)) return v; for (int i = 24; i >= 0; --i) { int ancestor = up[u][i]; if (ancestor && !isAncestor(ancestor, v, timeIn, timeOut)) { u = ancestor; } } return up[u][0]; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n; cin >> n; vector
>> graph(n + 1); vector
from(n), to(n), weight(n); // Input edges for (int i = 1; i < n; i++) { int u, v, w; cin >> u >> v >> w; from[i] = u; to[i] = v; weight[i] = w; graph[u].push_back({v, w}); graph[v].push_back({u, w}); } vector
timeIn(n + 1), timeOut(n + 1); vector
sumToRoot(n + 1, 0); vector
> up(n + 1, vector
(25, 0)); // Run DFS from root (1) dfs(1, 0, graph, timeIn, timeOut, sumToRoot, up); // Build binary lifting table for (int j = 1; j < 25; j++) { for (int i = 1; i <= n; i++) { int parent = up[i][j - 1]; up[i][j] = parent ? up[parent][j - 1] : 0; } } // Align edges so "from" is always parent and "to" is child for (int i = 1; i < n; i++) { if (timeIn[from[i]] > timeIn[to[i]]) swap(from[i], to[i]); } // Prepare array for segment tree using DFS order vector
dfsArray(n + 1, 0); for (int i = 1; i <= n; i++) dfsArray[timeIn[i]] = sumToRoot[i]; SegmentTree seg(n + 1); seg.build(1, 0, n, dfsArray); int q; cin >> q; while (q--) { int type; cin >> type; if (type == 1) { // Update edge weight int edgeIdx, newWeight; cin >> edgeIdx >> newWeight; int u = from[edgeIdx]; int v = to[edgeIdx]; long long delta = newWeight - weight[edgeIdx]; weight[edgeIdx] = newWeight; int l = timeIn[v], r = timeOut[v] - 1; if (l <= r) seg.update(1, l, r, 0, n, delta); } else if (type == 2) { // Query distance between two nodes int u, v; cin >> u >> v; long long distU = seg.query(1, timeIn[u], 0, n); long long distV = seg.query(1, timeIn[v], 0, n); if (isAncestor(u, v, timeIn, timeOut) || isAncestor(v, u, timeIn, timeOut)) { cout << llabs(distU - distV) << '\n'; } else { int lca = findLCA(u, v, up, timeIn, timeOut); long long distLCA = seg.query(1, timeIn[lca], 0, n); cout << llabs(distU + distV - 2 * distLCA) << '\n'; } } } return 0; }
Mark as private (unlisted)
for 30 minutes
for 6 hours
for 1 day
for 1 week
for 1 month
for 1 year
everlasting (like CCCP)