Problem p01771 (C++) — buggy submission, verdict: Runtime Error

#include <algorithm>
#include <bitset>
#include <cfloat>
#include <climits>
#include <cmath>
#include <cstdio>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>
using namespace std;

class LowestCommonAncestor {
private:
  vector<vector<int>> to;
  vector<int> depth;
  int climb(int curr, int dist) {
    int i = 0;
    while (dist > 0) {
      if (dist % 2 == 1)
        curr = to[curr][i];
      dist /= 2;
      ++i;
    }
    return curr;
  }

public:
  LowestCommonAncestor(const vector<vector<int>> &edges, int root) {
    int n = edges.size();
    to.assign(n, vector<int>());
    depth.resize(n);

    stack<tuple<int, int, int, int>> stk;
    stk.push(make_tuple(root, -1, 0, 0));
    while (!stk.empty()) {
      int curr, prev, cnt, i;
      tie(curr, prev, cnt, i) = stk.top();
      stk.pop();

      if (i == 0) {
        depth[curr] = cnt;
        if (prev != -1) {
          to[curr].push_back(prev);
          int j = prev;
          for (unsigned k = 0; k < to[j].size(); ++k) {
            j = to[j][k];
            to[curr].push_back(j);
          }
        }
      }

      if (i < (int)edges[curr].size()) {
        stk.push(make_tuple(curr, prev, cnt, i + 1));
        int next = edges[curr][i];
        if (next != prev)
          stk.push(make_tuple(next, curr, cnt + 1, 0));
      }
    }
  }
  // 2つのノードの最小共通祖先を取得
  int getAncestor(int a, int b) {
    int diff = depth[a] - depth[b];
    if (diff < 0)
      b = climb(b, -diff);
    else
      a = climb(a, diff);
    if (a == b)
      return a;

    for (int i = to[a].size() - 1; i >= 0; --i) {
      if (i < (int)to[a].size() && to[a][i] != to[b][i]) {
        a = to[a][i];
        b = to[b][i];
      }
    }
    return to[a][0];
  }
  // ノードの深さを取得
  int getDepth(int a) { return depth[a]; }
};

class SegmentTree {
private:
  typedef long long T1;
  typedef long long T2;

  // データの初期値、以下の条件を満たすこと
  // uniteData(v, INIT_DATA) == v
  enum { INIT_DATA = 0 };
  // 遅延の初期値、以下の条件を満たすこと
  // updateData(prev, size, INIT_DELAY) == prev
  // updateDelay(x, INIT_DELAY) == x
  enum { INIT_DELAY = 0 };

  // 長さがsizeの区間における前回の計算結果prevに対して、
  // 区間の各要素にパラメータxを用いた更新処理を適用した後の計算結果を返す
  T1 updateData(T1 prev, int size, T2 x) { return prev + x * size; }
  // パラメータx1,x2による2つの更新処理を順に適用した場合に対して、
  // 同じ結果になるような1つの更新処理のパラメータを返す
  T2 updateDelay(T2 x1, T2 x2) { return x1 + x2; }
  // 2つの区間の計算結果v1,v2に対して、
  // その2つの区間を統合した区間における計算結果を返す
  T1 uniteData(T1 v1, T1 v2) { return v1 + v2; }

  int n;
  vector<T1> data;
  vector<T2> delay;
  vector<int> tmp;
  void updateTree(int a, int b, int k, int l, int r, T2 x) {
    if (a <= l && r <= b) {
      data[k] = updateData(data[k], tmp[k], x);
      delay[k] = updateDelay(delay[k], x);
    } else if (a <= r && l <= b) {
      for (int i = 0; i < 2; ++i) {
        data[k * 2 + 1 + i] =
            updateData(data[k * 2 + 1 + i], tmp[k * 2 + 1 + i], delay[k]);
        delay[k * 2 + 1 + i] = updateDelay(delay[k * 2 + 1 + i], delay[k]);
      }
      delay[k] = INIT_DELAY;
      updateTree(a, b, k * 2 + 1, l, (l + r) / 2, x);
      updateTree(a, b, k * 2 + 2, (l + r + 1) / 2, r, x);
      data[k] = uniteData(data[k * 2 + 1], data[k * 2 + 2]);
    }
  }
  T1 getValue(int a, int b, int k, int l, int r) {
    if (a <= l && r <= b) {
      return data[k];
    } else if (a <= r && l <= b) {
      T1 v1 = getValue(a, b, k * 2 + 1, l, (l + r) / 2);
      T1 v2 = getValue(a, b, k * 2 + 2, (l + r + 1) / 2, r);
      return uniteData(v1, v2);
    } else {
      return INIT_DATA;
    }
  }

public:
  SegmentTree(const vector<int> &v) {
    int n0 = v.size();
    n = 1;
    while (n < n0)
      n *= 2;
    data.assign(2 * n - 1, INIT_DATA);
    delay.assign(2 * n - 1, INIT_DELAY);

    tmp.resize(2 * n - 1);
    for (unsigned i = 0; i < v.size(); ++i)
      tmp[n - 1 + i] = v[i];
    for (int k = n - 2; k >= 0; --k)
      tmp[k] = tmp[k * 2 + 1] + tmp[k * 2 + 2];
  }
  // 区間[a,b]の要素にパラメータxによる更新処理を適用
  void update(int a, int b, T2 x) { updateTree(a, b, 0, 0, n - 1, x); }
  // 区間[a,b]の計算結果を返す
  T1 get(int a, int b) {
    updateTree(a, b, 0, 0, n - 1, 0);
    return getValue(a, b, 0, 0, n - 1);
  }
};

int main() {
  int n, q;
  cin >> n >> q;

  vector<vector<int>> edges(n);
  for (int i = 0; i < n - 1; ++i) {
    int a, b;
    cin >> a >> b;
    edges[a].push_back(b);
    edges[b].push_back(a);
  }
  LowestCommonAncestor lca(edges, 0);

  vector<int> v;
  vector<int> left(n), right(n);
  stack<tuple<int, int, int>> stk;
  stk.push(make_tuple(0, -1, 0));
  while (!stk.empty()) {
    int curr, prev, i;
    tie(curr, prev, i) = stk.top();
    stk.pop();

    if (i == edges[curr].size()) {
      right[curr] = v.size();
      v.push_back(-1);
      continue;
    }
    stk.push(make_tuple(curr, prev, i + 1));

    int next = edges[curr][i];
    if (next != prev) {
      v.push_back(1);
      left[next] = v.size();
      stk.push(make_tuple(next, curr, 0));
    }
  }
  v.pop_back();
  SegmentTree st(v);

  while (--q >= 0) {
    int x, a, b;
    cin >> x >> a >> b;

    if (x == 0) {
      int c = lca.getAncestor(a, b);
      long long ans =
          st.get(left[c], left[a] - 1) + st.get(left[c], left[b] - 1);
      cout << ans << endl;
    } else {
      st.update(left[a], right[a] - 1, b);
    }
  }

  return 0;
}

Error: 0

Fixed submission:

#include <algorithm>
#include <bitset>
#include <cfloat>
#include <climits>
#include <cmath>
#include <cstdio>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>
using namespace std;

class LowestCommonAncestor {
private:
  vector<vector<int>> to;
  vector<int> depth;
  void dfs(const vector<vector<int>> &edges, int curr, int prev, int cnt) {
    depth[curr] = cnt;
    if (prev != -1) {
      to[curr].push_back(prev);
      int j = prev;
      for (unsigned k = 0; k < to[j].size(); ++k) {
        j = to[j][k];
        to[curr].push_back(j);
      }
    }
    for (unsigned i = 0; i < edges[curr].size(); ++i) {
      int next = edges[curr][i];
      if (next != prev)
        dfs(edges, next, curr, cnt + 1);
    }
  }
  int climb(int curr, int dist) {
    int i = 0;
    while (dist > 0) {
      if (dist % 2 == 1)
        curr = to[curr][i];
      dist /= 2;
      ++i;
    }
    return curr;
  }

public:
  LowestCommonAncestor(const vector<vector<int>> &edges, int root) {
    int n = edges.size();
    to.assign(n, vector<int>());
    depth.resize(n);

    stack<tuple<int, int, int, int>> stk;
    stk.push(make_tuple(root, -1, 0, 0));
    while (!stk.empty()) {
      int curr, prev, cnt, i;
      tie(curr, prev, cnt, i) = stk.top();
      stk.pop();

      if (i == 0) {
        depth[curr] = cnt;
        if (prev != -1) {
          to[curr].push_back(prev);
          int j = prev;
          for (unsigned k = 0; k < to[j].size(); ++k) {
            j = to[j][k];
            to[curr].push_back(j);
          }
        }
      }

      if (i < (int)edges[curr].size()) {
        stk.push(make_tuple(curr, prev, cnt, i + 1));
        int next = edges[curr][i];
        if (next != prev)
          stk.push(make_tuple(next, curr, cnt + 1, 0));
      }
    }

    dfs(edges, root, -1, 0);
  }
  // 2つのノードの最小共通祖先を取得
  int getAncestor(int a, int b) {
    int diff = depth[a] - depth[b];
    if (diff < 0)
      b = climb(b, -diff);
    else
      a = climb(a, diff);
    if (a == b)
      return a;

    for (int i = to[a].size() - 1; i >= 0; --i) {
      if (i < (int)to[a].size() && to[a][i] != to[b][i]) {
        a = to[a][i];
        b = to[b][i];
      }
    }
    return to[a][0];
  }
  // ノードの深さを取得
  int getDepth(int a) { return depth[a]; }
};

class SegmentTree {
private:
  typedef long long T1;
  typedef long long T2;

  // データの初期値、以下の条件を満たすこと
  // uniteData(v, INIT_DATA) == v
  enum { INIT_DATA = 0 };
  // 遅延の初期値、以下の条件を満たすこと
  // updateData(prev, size, INIT_DELAY) == prev
  // updateDelay(x, INIT_DELAY) == x
  enum { INIT_DELAY = 0 };

  // 長さがsizeの区間における前回の計算結果prevに対して、
  // 区間の各要素にパラメータxを用いた更新処理を適用した後の計算結果を返す
  T1 updateData(T1 prev, int size, T2 x) { return prev + x * size; }
  // パラメータx1,x2による2つの更新処理を順に適用した場合に対して、
  // 同じ結果になるような1つの更新処理のパラメータを返す
  T2 updateDelay(T2 x1, T2 x2) { return x1 + x2; }
  // 2つの区間の計算結果v1,v2に対して、
  // その2つの区間を統合した区間における計算結果を返す
  T1 uniteData(T1 v1, T1 v2) { return v1 + v2; }

  int n;
  vector<T1> data;
  vector<T2> delay;
  vector<int> tmp;
  void updateTree(int a, int b, int k, int l, int r, T2 x) {
    if (a <= l && r <= b) {
      data[k] = updateData(data[k], tmp[k], x);
      delay[k] = updateDelay(delay[k], x);
    } else if (a <= r && l <= b) {
      for (int i = 0; i < 2; ++i) {
        data[k * 2 + 1 + i] =
            updateData(data[k * 2 + 1 + i], tmp[k * 2 + 1 + i], delay[k]);
        delay[k * 2 + 1 + i] = updateDelay(delay[k * 2 + 1 + i], delay[k]);
      }
      delay[k] = INIT_DELAY;
      updateTree(a, b, k * 2 + 1, l, (l + r) / 2, x);
      updateTree(a, b, k * 2 + 2, (l + r + 1) / 2, r, x);
      data[k] = uniteData(data[k * 2 + 1], data[k * 2 + 2]);
    }
  }
  T1 getValue(int a, int b, int k, int l, int r) {
    if (a <= l && r <= b) {
      return data[k];
    } else if (a <= r && l <= b) {
      T1 v1 = getValue(a, b, k * 2 + 1, l, (l + r) / 2);
      T1 v2 = getValue(a, b, k * 2 + 2, (l + r + 1) / 2, r);
      return uniteData(v1, v2);
    } else {
      return INIT_DATA;
    }
  }

public:
  SegmentTree(const vector<int> &v) {
    int n0 = v.size();
    n = 1;
    while (n < n0)
      n *= 2;
    data.assign(2 * n - 1, INIT_DATA);
    delay.assign(2 * n - 1, INIT_DELAY);

    tmp.resize(2 * n - 1);
    for (unsigned i = 0; i < v.size(); ++i)
      tmp[n - 1 + i] = v[i];
    for (int k = n - 2; k >= 0; --k)
      tmp[k] = tmp[k * 2 + 1] + tmp[k * 2 + 2];
  }
  // 区間[a,b]の要素にパラメータxによる更新処理を適用
  void update(int a, int b, T2 x) { updateTree(a, b, 0, 0, n - 1, x); }
  // 区間[a,b]の計算結果を返す
  T1 get(int a, int b) {
    updateTree(a, b, 0, 0, n - 1, 0);
    return getValue(a, b, 0, 0, n - 1);
  }
};

int main() {
  int n, q;
  cin >> n >> q;

  vector<vector<int>> edges(n);
  for (int i = 0; i < n - 1; ++i) {
    int a, b;
    cin >> a >> b;
    edges[a].push_back(b);
    edges[b].push_back(a);
  }
  LowestCommonAncestor lca(edges, 0);

  vector<int> v;
  vector<int> left(n), right(n);
  stack<tuple<int, int, int>> stk;
  stk.push(make_tuple(0, -1, 0));
  while (!stk.empty()) {
    int curr, prev, i;
    tie(curr, prev, i) = stk.top();
    stk.pop();

    if (i == edges[curr].size()) {
      right[curr] = v.size();
      v.push_back(-1);
      continue;
    }
    stk.push(make_tuple(curr, prev, i + 1));

    int next = edges[curr][i];
    if (next != prev) {
      v.push_back(1);
      left[next] = v.size();
      stk.push(make_tuple(next, curr, 0));
    }
  }
  v.pop_back();
  SegmentTree st(v);

  while (--q >= 0) {
    int x, a, b;
    cin >> x >> a >> b;

    if (x == 0) {
      int c = lca.getAncestor(a, b);
      long long ans =
          st.get(left[c], left[a] - 1) + st.get(left[c], left[b] - 1);
      cout << ans << endl;
    } else {
      st.update(left[a], right[a] - 1, b);
    }
  }

  return 0;
}