Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <bits/stdc++.h>
- #define all(x) (x).begin(), (x).end()
- using namespace std;
- using ll = long long;
- const int N = 100100;
- vector<int> g[N];
- int depth[N];
- int tsize[N];
- int par[N][20];
- int hld[N];
- int inhld[N];
- int hldsz[N];
- int top[N];
- struct SegmentTree {
- vector<ll> t;
- int n;
- SegmentTree(int n = 0) : n(n) {
- t.assign(n * 4, 0);
- }
- void Upd(int v, int tl, int tr, int i, int val) {
- if (tl + 1 == tr) {
- t[v] += val;
- } else {
- int tm = (tl + tr) / 2;
- if (i < tm) {
- Upd(v * 2 + 1, tl, tm, i, val);
- } else {
- Upd(v * 2 + 2, tm, tr, i, val);
- }
- t[v] = max(t[v * 2 + 1], t[v * 2 + 2]);
- }
- }
- ll Get(int v, int tl, int tr, int l, int r) {
- if (tl >= r || tr <= l) return 0;
- if (tl >= l && tr <= r) return t[v];
- int tm = (tl + tr) / 2;
- return max(Get(v * 2 + 1, tl, tm, l, r), Get(v * 2 + 2, tm, tr, l, r));
- }
- };
- vector<SegmentTree> t;
- void Dfs(int from, int p, int h = 0) {
- depth[from] = h;
- par[from][0] = p;
- tsize[from] = 1;
- for (int i = 1; i < 20; i++) {
- par[from][i] = par[par[from][i - 1]][i - 1];
- }
- for (int v : g[from]) {
- if (v != p) {
- Dfs(v, from, h + 1);
- tsize[from] += tsize[v];
- }
- }
- }
- void Build(int from, int p, int& index) {
- hld[from] = index;
- int itr = 0;
- for (int v : g[from]) {
- if (v != p) {
- itr++;
- index += itr > 1;
- Build(v, from, index);
- }
- }
- }
- void BuildHld(int n) {
- Dfs(0, 0);
- for (int i = 0; i < n; i++) {
- sort(all(g[i]), [&] (int i, int j) { return tsize[i] > tsize[j];});
- }
- int sz = 0;
- Build(0, 0, sz);
- sz++;
- vector<vector<int>> arr(sz);
- for (int i = 0; i < n; i++) {
- arr[hld[i]].push_back(i);
- }
- for (int i = 0; i < sz; i++) {
- sort(all(arr[i]), [&] (int i, int j) { return depth[i] < depth[j]; });
- for (int j = 0; j < arr[i].size(); j++) {
- inhld[arr[i][j]] = j;
- }
- t.emplace_back(arr[i].size());
- top[i] = arr[i][0];
- }
- }
- int lca(int a, int b) {
- if (depth[a] < depth[b]) swap(a, b);
- for (int i = 19; i >= 0; i--) {
- if (depth[par[a][i]] >= depth[b]) {
- a = par[a][i];
- }
- }
- if (a == b) return a;
- for (int i = 19; i >= 0; i--) {
- if (par[a][i] != par[b][i]) {
- a = par[a][i];
- b = par[b][i];
- }
- }
- return par[a][0];
- }
- void Upd(int a, int val) {
- auto& tree = t[hld[a]];
- tree.Upd(0, 0, tree.n, inhld[a], val);
- }
- ll Get(int a, int b) {
- int c = lca(a, b);
- ll ans = 0;
- while (hld[a] != hld[c]) {
- auto& tree = t[hld[a]];
- ans = max(ans, tree.Get(0, 0, tree.n, 0, inhld[a] + 1));
- a = par[top[hld[a]]][0];
- }
- while (hld[b] != hld[c]) {
- auto& tree = t[hld[b]];
- ans = max(ans, tree.Get(0, 0, tree.n, 0, inhld[b] + 1));
- b = par[top[hld[b]]][0];
- }
- if (depth[a] > depth[b]) swap(a, b);
- auto& tree = t[hld[a]];
- ans = max(ans, tree.Get(0, 0, tree.n, inhld[a], inhld[b] + 1));
- return ans;
- }
- int main() {
- ios_base::sync_with_stdio(false);
- cin.tie(nullptr);
- cout.tie(nullptr);
- int n;
- cin >> n;
- for (int i = 0; i + 1 < n; i++) {
- int f, t;
- cin >> f >> t;
- f--, t--;
- g[f].push_back(t);
- g[t].push_back(f);
- }
- BuildHld(n);
- int q;
- cin >> q;
- while (q--) {
- char ch;
- int a, b;
- cin >> ch >> a >> b;
- if (ch == 'I') {
- a--;
- Upd(a, b);
- } else {
- a--, b--;
- cout << Get(a, b) << "\n";
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement