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

#include <bits/stdc++.h>
using namespace std;

#define for_(i, a, b) for (int i = (a); i < (b); ++i)
#define for_rev(i, a, b) for (int i = (a); i >= (b); --i)
#define allof(a) (a).begin(), (a).end()
#define minit(a, b) memset(a, b, sizeof(a))
#define cauto const auto

typedef long long lint;
typedef pair<int, int> pii;
template <typename T> inline void maxUpdate(T &a, T b) { a = max(a, b); }

template <typename DATA> class SegmentTreeR {
private:
  int size__;
  vector<DATA> data, adds;

  inline int left_t(int k) { return (k << 1) + 1; }
  inline int right_t(int k) { return (k << 1) + 2; }
  inline int center(int l, int r) { return (l + r) >> 1; }

public:
  SegmentTreeR() {}

  SegmentTreeR(int n, DATA ini, DATA lini) {
    for (size__ = 1; size__ < n; size__ <<= 1)
      ;
    data.assign(2 * size__ - 1, ini);
    adds.assign(2 * size__ - 1, lini);
  }

  void rangeAdd(int a, int b, DATA x) { rangeAdd(a, b, x, 0, 0, size__); }

  void rangeAdd(int a, int b, DATA x, int k, int l, int r) {
    if (r <= a || b <= l)
      return;
    if (a <= l && r <= b) {
      adds[k] += x;
      return;
    }

    data[k] += x * (min(r, b) - max(l, a));
    rangeAdd(a, b, x, left_t(k), l, center(l, r));
    rangeAdd(a, b, x, right_t(k), center(l, r), r);
  }

  DATA query(int a, int b) { return query(a, b, 0, 0, size__); }

  DATA query(int a, int b, int k, int l, int r) {
    if (r <= a || b <= l)
      return 0;
    if (a <= l && r <= b)
      return data[k] + adds[k] * (r - l);
    return query(a, b, left_t(k), l, center(l, r)) +
           query(a, b, right_t(k), center(l, r), r) +
           adds[k] * (min(r, b) - max(l, a));
  }

  int size() { return size__; }
};

class H_L_Decomp {
public:
  struct Node {
    int parent;
    vector<int> path;
    unordered_map<int, int> vid;
    vector<int> adj;
  };

private:
  int N;
  vector<pii> part_max;

  void partCalc(int root, vector<vector<int>> &adj) {
    vector<int> vis(N, 0);
    vector<int> sum(N, 1);

    stack<pii> vstk;
    vstk.push(pii(root, -1));

    while (!vstk.empty()) {
      int v = vstk.top().first;
      int p = vstk.top().second;

      ++vis[v];

      if (vis[v] == 1) {
        for (int u : adj[v])
          if (u != p)
            vstk.push(pii(u, v));
      }

      if (vis[v] == 2) {
        vstk.pop();
        if (p != -1)
          sum[p] += sum[v];
      }
    }

    for_(v, 0, N) for (int u : adj[v]) {
      maxUpdate(part_max[v], pii(sum[u], u));
    }
  }

  int node_cnt;
  vector<Node> nodes;

  void decomp(int root, vector<vector<int>> &adj) {
    stack<int> vstk, nstk;
    stack<pii> pstk;
    vstk.push(root);
    nstk.push(-1);
    pstk.push(pii(-1, -1));

    while (!vstk.empty()) {
      int v = vstk.top();
      vstk.pop();
      int cur_node = nstk.top();
      nstk.pop();
      if (cur_node == -1)
        cur_node = node_cnt;
      int par = pstk.top().second;
      int par_node = pstk.top().first;
      pstk.pop();

      if (par != -1) {
        nodes[par_node].adj.push_back(nodes.size());
        nodes.push_back(
            Node{par, vector<int>(), unordered_map<int, int>(), vector<int>()});
      }

      nodes[cur_node].vid[v] = nodes[cur_node].path.size();
      nodes[cur_node].path.push_back(v);

      int heavy = part_max[v].second;

      if (heavy == -1) {
        ++node_cnt;
      } else {
        for (int u : adj[v]) {
          if (u != heavy) {
            vstk.push(u);
            nstk.push(-1);
            pstk.push(pii(cur_node, v));
          }
        }

        vstk.push(heavy);
        nstk.push(cur_node);
        pstk.push(pii(-1, -1));
      }
    }
  }

public:
  H_L_Decomp() {}

  vector<Node> decomposition(vector<vector<int>> &adj, int root) {
    N = adj.size();

    part_max.assign(N, pii(-1, -1));
    partCalc(root, adj);

    nodes.clear();

    node_cnt = 0;
    nodes.push_back(
        Node{-1, vector<int>(), unordered_map<int, int>(), vector<int>()});

    decomp(root, adj);

    return nodes;
  }
};

int N, Q, depth[150010], parent[150010][25];
vector<vector<int>> adj;

void makeLCA() {
  stack<pii> vstk;
  stack<int> pstk;
  vstk.push(pii(0, 0));
  pstk.push(-1);

  while (!vstk.empty()) {
    int v = vstk.top().first;
    int d = vstk.top().second;
    vstk.pop();
    depth[v] = d;
    int p = pstk.top();
    pstk.pop();
    parent[v][0] = p;

    for (int u : adj[v])
      if (u != p) {
        vstk.push(pii(u, d + 1));
        pstk.push(v);
      }
  }

  for_(k, 0, 24) for_(v, 0, N) {
    if (parent[v][k] == -1)
      parent[v][k + 1] = -1;
    else
      parent[v][k + 1] = parent[parent[v][k]][k];
  }
}

inline int getLCA(int u, int v) {
  if (depth[u] > depth[v])
    swap(u, v);

  for_(k, 0, 25) if ((depth[v] - depth[u]) >> k & 1) v = parent[v][k];

  if (u == v)
    return u;

  for_rev(k, 24, 0) {
    if (parent[u][k] != parent[v][k]) {
      u = parent[u][k];
      v = parent[v][k];
    }
  }

  return parent[u][0];
}

vector<H_L_Decomp::Node> hld;
int M;
vector<int> pathId;
vector<SegmentTreeR<lint>> segv;

vector<int> partId;
vector<pii> partRange;
SegmentTreeR<lint> parCost;

void hldPartRangeCalc() {
  vector<int> vis(N, -1);

  int id = 0;

  stack<int> vstk;
  vstk.push(0);

  while (!vstk.empty()) {
    int v = vstk.top();

    if (vis[v] == -1) {
      vis[v] = id;
      for (int u : adj[v])
        vstk.push(u);
    } else {
      vstk.pop();
      int t = pathId[v];
      partRange[v] = pii(vis[v], id);

      if (hld[t].vid[v] == 0) {
        partId[t] = id;
        ++id;
      }
    }
  }
}

inline lint getCost(int v) {
  lint res = 0;

  while (v >= 0) {
    int t = pathId[v];
    int rgt = hld[t].vid[v];
    res += parCost.query(partId[t], partId[t] + 1) * (rgt + 1);
    res += segv[t].query(0, rgt);
    v = hld[t].parent;
  }

  return res;
}

int main() {
  cin >> N >> Q;

  adj.assign(N, vector<int>());

  for_(i, 0, N - 1) {
    int u, v;
    scanf("%d %d", &u, &v);
    adj[u].push_back(v);
  }

  minit(parent, -1);

  makeLCA();

  hld = H_L_Decomp().decomposition(adj, 0);

  M = hld.size();

  pathId.assign(N, -1);

  for_(i, 0, M) {
    for (int v : hld[i].path)
      pathId[v] = i;
    segv.push_back(SegmentTreeR<lint>(hld[i].path.size(), 0, 0));
  }

  partId.assign(M, -1);
  partRange.assign(N, pii(0, 0));
  parCost = SegmentTreeR<lint>(M, 0, 0);

  hldPartRangeCalc();

  for_(i, 0, Q) {
    int q, a, b;
    scanf("%d %d %d", &q, &a, &b);

    if (q) {
      int t = pathId[a];
      int lft = hld[t].vid[a];
      segv[t].rangeAdd(lft, hld[t].path.size(), b);
      parCost.rangeAdd(partRange[a].first, partRange[a].second, b);
    } else {
      int lca = getLCA(a, b);
      lint A = getCost(a), B = getCost(b), C = getCost(lca);
      // cout << A + B - 2 * C << endl;
      printf("%ld\\n", A + B - 2 * C);
    }
  }
}

Error: 0

Fixed submission:

#include <bits/stdc++.h>
using namespace std;

#define for_(i, a, b) for (int i = (a); i < (b); ++i)
#define for_rev(i, a, b) for (int i = (a); i >= (b); --i)
#define allof(a) (a).begin(), (a).end()
#define minit(a, b) memset(a, b, sizeof(a))
#define cauto const auto

typedef long long lint;
typedef pair<int, int> pii;
template <typename T> inline void maxUpdate(T &a, T b) { a = max(a, b); }

template <typename DATA> class SegmentTreeR {
private:
  int size__;
  vector<DATA> data, adds;

  inline int left_t(int k) { return (k << 1) + 1; }
  inline int right_t(int k) { return (k << 1) + 2; }
  inline int center(int l, int r) { return (l + r) >> 1; }

public:
  SegmentTreeR() {}

  SegmentTreeR(int n, DATA ini, DATA lini) {
    for (size__ = 1; size__ < n; size__ <<= 1)
      ;
    data.assign(2 * size__ - 1, ini);
    adds.assign(2 * size__ - 1, lini);
  }

  void rangeAdd(int a, int b, DATA x) { rangeAdd(a, b, x, 0, 0, size__); }

  void rangeAdd(int a, int b, DATA x, int k, int l, int r) {
    if (r <= a || b <= l)
      return;
    if (a <= l && r <= b) {
      adds[k] += x;
      return;
    }

    data[k] += x * (min(r, b) - max(l, a));
    rangeAdd(a, b, x, left_t(k), l, center(l, r));
    rangeAdd(a, b, x, right_t(k), center(l, r), r);
  }

  DATA query(int a, int b) { return query(a, b, 0, 0, size__); }

  DATA query(int a, int b, int k, int l, int r) {
    if (r <= a || b <= l)
      return 0;
    if (a <= l && r <= b)
      return data[k] + adds[k] * (r - l);
    return query(a, b, left_t(k), l, center(l, r)) +
           query(a, b, right_t(k), center(l, r), r) +
           adds[k] * (min(r, b) - max(l, a));
  }

  int size() { return size__; }
};

class H_L_Decomp {
public:
  struct Node {
    int parent;
    vector<int> path;
    unordered_map<int, int> vid;
    vector<int> adj;
  };

private:
  int N;
  vector<pii> part_max;

  void partCalc(int root, vector<vector<int>> &adj) {
    vector<int> vis(N, 0);
    vector<int> sum(N, 1);

    stack<pii> vstk;
    vstk.push(pii(root, -1));

    while (!vstk.empty()) {
      int v = vstk.top().first;
      int p = vstk.top().second;

      ++vis[v];

      if (vis[v] == 1) {
        for (int u : adj[v])
          if (u != p)
            vstk.push(pii(u, v));
      }

      if (vis[v] == 2) {
        vstk.pop();
        if (p != -1)
          sum[p] += sum[v];
      }
    }

    for_(v, 0, N) for (int u : adj[v]) {
      maxUpdate(part_max[v], pii(sum[u], u));
    }
  }

  int node_cnt;
  vector<Node> nodes;

  void decomp(int root, vector<vector<int>> &adj) {
    stack<int> vstk, nstk;
    stack<pii> pstk;
    vstk.push(root);
    nstk.push(-1);
    pstk.push(pii(-1, -1));

    while (!vstk.empty()) {
      int v = vstk.top();
      vstk.pop();
      int cur_node = nstk.top();
      nstk.pop();
      if (cur_node == -1)
        cur_node = node_cnt;
      int par = pstk.top().second;
      int par_node = pstk.top().first;
      pstk.pop();

      if (par != -1) {
        nodes[par_node].adj.push_back(nodes.size());
        nodes.push_back(
            Node{par, vector<int>(), unordered_map<int, int>(), vector<int>()});
      }

      nodes[cur_node].vid[v] = nodes[cur_node].path.size();
      nodes[cur_node].path.push_back(v);

      int heavy = part_max[v].second;

      if (heavy == -1) {
        ++node_cnt;
      } else {
        for (int u : adj[v]) {
          if (u != heavy) {
            vstk.push(u);
            nstk.push(-1);
            pstk.push(pii(cur_node, v));
          }
        }

        vstk.push(heavy);
        nstk.push(cur_node);
        pstk.push(pii(-1, -1));
      }
    }
  }

public:
  H_L_Decomp() {}

  vector<Node> decomposition(vector<vector<int>> &adj, int root) {
    N = adj.size();

    part_max.assign(N, pii(-1, -1));
    partCalc(root, adj);

    nodes.clear();

    node_cnt = 0;
    nodes.push_back(
        Node{-1, vector<int>(), unordered_map<int, int>(), vector<int>()});

    decomp(root, adj);

    return nodes;
  }
};

int N, Q, depth[150010], parent[150010][25];
vector<vector<int>> adj;

void makeLCA() {
  stack<pii> vstk;
  stack<int> pstk;
  vstk.push(pii(0, 0));
  pstk.push(-1);

  while (!vstk.empty()) {
    int v = vstk.top().first;
    int d = vstk.top().second;
    vstk.pop();
    depth[v] = d;
    int p = pstk.top();
    pstk.pop();
    parent[v][0] = p;

    for (int u : adj[v])
      if (u != p) {
        vstk.push(pii(u, d + 1));
        pstk.push(v);
      }
  }

  for_(k, 0, 24) for_(v, 0, N) {
    if (parent[v][k] == -1)
      parent[v][k + 1] = -1;
    else
      parent[v][k + 1] = parent[parent[v][k]][k];
  }
}

inline int getLCA(int u, int v) {
  if (depth[u] > depth[v])
    swap(u, v);

  for_(k, 0, 25) if ((depth[v] - depth[u]) >> k & 1) v = parent[v][k];

  if (u == v)
    return u;

  for_rev(k, 24, 0) {
    if (parent[u][k] != parent[v][k]) {
      u = parent[u][k];
      v = parent[v][k];
    }
  }

  return parent[u][0];
}

vector<H_L_Decomp::Node> hld;
int M;
vector<int> pathId;
vector<SegmentTreeR<lint>> segv;

vector<int> partId;
vector<pii> partRange;
SegmentTreeR<lint> parCost;

void hldDfs(int v, int p, int &id) {
  int lft = id;
  int t = pathId[v];

  for (int u : adj[v])
    if (u != p)
      hldDfs(u, v, id);

  int rgt = id;
  partRange[v] = pii(lft, rgt);

  if (hld[t].vid[v] == 0) {
    partId[t] = id;
    ++id;
  }
}

inline lint getCost(int v) {
  lint res = 0;

  while (v >= 0) {
    int t = pathId[v];
    int rgt = hld[t].vid[v];
    res += parCost.query(partId[t], partId[t] + 1) * (rgt + 1);
    res += segv[t].query(0, rgt);
    v = hld[t].parent;
  }

  return res;
}

int main() {
  cin >> N >> Q;

  adj.assign(N, vector<int>());

  for_(i, 0, N - 1) {
    int u, v;
    scanf("%d %d", &u, &v);
    adj[u].push_back(v);
  }

  minit(parent, -1);

  makeLCA();

  hld = H_L_Decomp().decomposition(adj, 0);

  M = hld.size();

  pathId.assign(N, -1);

  for_(i, 0, M) {
    for (int v : hld[i].path)
      pathId[v] = i;
    segv.push_back(SegmentTreeR<lint>(hld[i].path.size(), 0, 0));
  }

  partId.assign(M, -1);
  partRange.assign(N, pii(0, 0));
  parCost = SegmentTreeR<lint>(M, 0, 0);

  int id = 0;
  hldDfs(0, -1, id);

  for_(i, 0, Q) {
    int q, a, b;
    scanf("%d %d %d", &q, &a, &b);

    if (q) {
      int t = pathId[a];
      int lft = hld[t].vid[a];
      segv[t].rangeAdd(lft, hld[t].path.size(), b);
      parCost.rangeAdd(partRange[a].first, partRange[a].second, b);
    } else {
      int lca = getLCA(a, b);
      lint A = getCost(a), B = getCost(b), C = getCost(lca);
      cout << A + B - 2 * C << endl;
      // printf("%ld\\n", A + B - 2 * C);
    }
  }
}