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;
    vector<int> adj;
  };

  struct VertexInfo {
    int nodeID, pos;
  };

  struct Result {
    vector<Node> nodes;
    vector<VertexInfo> vinfo;
  };

private:
  int N;
  const vector<vector<int>> &adj;

  vector<Node> nodes;
  vector<VertexInfo> vinfo;

  vector<int> child_sum;
  vector<pii> part_max;

  void partDfs(int v) {
    child_sum[v] = 1;

    for (auto &u : adj[v]) {
      partDfs(u);
      child_sum[v] += child_sum[u];
      maxUpdate(part_max[v], pii(child_sum[u], u));
    }
  }

  void decompDfs_VerStack(int v) {
    stack<pii> stk;
    stk.push(pii(v, 1));

    while (!stk.empty()) {
      pii p = stk.top();
      stk.pop();
      int v = p.first, ns = p.second;

      vinfo[v].nodeID = ns - 1;
      vinfo[v].pos = nodes[ns - 1].path.size();

      nodes[ns - 1].path.push_back(v);

      if (part_max[v].second != -1) {
        for (auto &u : adj[v]) {
          if (u != part_max[v].second) {
            nodes[vinfo[v].nodeID].adj.push_back(ns);
            nodes.push_back(Node{v, vector<int>(), vector<int>()});

            stk.push(pii(u, nodes.size()));
          }
        }

        stk.push(pii(part_max[v].second, ns));
      }
    }
  }

  /*
  void decompDfs(int v) {
          vinfo[v].nodeID = nodes.size() - 1;
          vinfo[v].pos = nodes[ nodes.size() - 1 ].path.size();

          nodes[nodes.size() - 1].path.push_back(v);

          if (part_max[v].second != -1) {
                  decompDfs(part_max[v].second);

                  for (auto& u : adj[v]) {
                          if (u != part_max[v].second) {
                                  nodes[ vinfo[v].nodeID
  ].adj.push_back(nodes.size()); nodes.push_back(Node{v, vector< int >(),
  vector< int >()});

                                  decompDfs(u);
                          }
                  }
          }
  }
  */

public:
  H_L_Decomp(const vector<vector<int>> &_adj_) : N(_adj_.size()), adj(_adj_) {}

  Result decomposition(int root) {
    child_sum.assign(N, 0);
    part_max.assign(N, pii(-1, -1));

    partDfs(root);

    child_sum.clear();

    nodes.clear();
    nodes.push_back(Node{-1, vector<int>(), vector<int>()});

    vinfo = vector<VertexInfo>(N);

    decompDfs_VerStack(0);
    // decompDfs(root);

    return Result{nodes, vinfo};
  }
};

class LCA {
public:
  struct Result {
    vector<int> depth;

    int K;
    vector<vector<int>> parent;

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

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

      if (u == v)
        return u;

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

      return parent[u][0];
    }
  };

private:
  int N;
  const vector<vector<int>> &adj;

  vector<int> depth;
  vector<vector<int>> parent;

  void depthDfs(int v) {
    for (auto &u : adj[v]) {
      parent[u][0] = v;
      depth[u] = depth[v] + 1;
      depthDfs(u);
    }
  }

public:
  LCA(const vector<vector<int>> &_adj_) : N(_adj_.size()), adj(_adj_) {}

  Result generate(int root) {
    depth.assign(N, 0);

    int S = 1, K = 1;
    for (; S < N; S <<= 1)
      ++K;

    parent.assign(N, vector<int>(K, -1));

    depthDfs(root);

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

    return Result{depth, K, parent};
  }
};

int N, Q;
vector<vector<int>> adj;

LCA::Result lca;

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

int cur_id;
vector<int> partID;
vector<pii> partRange;
SegmentTreeR<lint> partCost;

void hldDfs(int v) {
  partRange[v].first = cur_id;

  for (auto &u : adj[v])
    hldDfs(u);

  partRange[v].second = cur_id;

  if (hld.vinfo[v].pos == 0) {
    partID[hld.vinfo[v].nodeID] = cur_id;
    ++cur_id;
  }
}

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

  while (v >= 0) {
    int t = hld.vinfo[v].nodeID;
    int rgt = hld.vinfo[v].pos;
    res += partCost.query(partID[t], partID[t] + 1) * (rgt + 1);
    res += segv[t].query(0, rgt);
    v = hld.nodes[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);
  }

  lca = LCA(adj).generate(0);

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

  M = hld.nodes.size();

  for_(i, 0, M)
      segv.push_back(SegmentTreeR<lint>(hld.nodes[i].path.size(), 0, 0));

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

  cur_id = 0;
  hldDfs(0);

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

    if (q) {
      int t = hld.vinfo[a].nodeID;
      segv[t].rangeAdd(hld.vinfo[a].pos, hld.nodes[t].path.size(), b);
      partCost.rangeAdd(partRange[a].first, partRange[a].second, b);
    } else {
      int c = lca.getLCA(a, b);
      lint A = getCost(a), B = getCost(b), C = getCost(c);
      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;
    vector<int> adj;
  };

  struct VertexInfo {
    int nodeID, pos;
  };

  struct Result {
    vector<Node> nodes;
    vector<VertexInfo> vinfo;
  };

private:
  int N;
  const vector<vector<int>> &adj;

  vector<Node> nodes;
  vector<VertexInfo> vinfo;

  vector<int> child_sum;
  vector<pii> part_max;

  void partDfs(int v) {
    child_sum[v] = 1;

    for (auto &u : adj[v]) {
      partDfs(u);
      child_sum[v] += child_sum[u];
      maxUpdate(part_max[v], pii(child_sum[u], u));
    }
  }

  void decompDfs(int v) {
    vinfo[v].nodeID = nodes.size() - 1;
    vinfo[v].pos = nodes[nodes.size() - 1].path.size();

    nodes[nodes.size() - 1].path.push_back(v);

    if (part_max[v].second != -1) {
      decompDfs(part_max[v].second);

      for (auto &u : adj[v]) {
        if (u != part_max[v].second) {
          nodes[vinfo[v].nodeID].adj.push_back(nodes.size());
          nodes.push_back(Node{v, vector<int>(), vector<int>()});

          decompDfs(u);
        }
      }
    }
  }

public:
  H_L_Decomp(const vector<vector<int>> &_adj_) : N(_adj_.size()), adj(_adj_) {}

  Result decomposition(int root) {
    child_sum.assign(N, 0);
    part_max.assign(N, pii(-1, -1));

    partDfs(root);

    child_sum.clear();

    nodes.clear();
    nodes.push_back(Node{-1, vector<int>(), vector<int>()});

    vinfo = vector<VertexInfo>(N);

    decompDfs(root);

    return Result{nodes, vinfo};
  }
};

class LCA {
public:
  struct Result {
    vector<int> depth;

    int K;
    vector<vector<int>> parent;

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

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

      if (u == v)
        return u;

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

      return parent[u][0];
    }
  };

private:
  int N;
  const vector<vector<int>> &adj;

  vector<int> depth;
  vector<vector<int>> parent;

  void depthDfs(int v) {
    for (auto &u : adj[v]) {
      parent[u][0] = v;
      depth[u] = depth[v] + 1;
      depthDfs(u);
    }
  }

public:
  LCA(const vector<vector<int>> &_adj_) : N(_adj_.size()), adj(_adj_) {}

  Result generate(int root) {
    depth.assign(N, 0);

    int S = 1, K = 1;
    for (; S < N; S <<= 1)
      ++K;

    parent.assign(N, vector<int>(K, -1));

    depthDfs(root);

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

    return Result{depth, K, parent};
  }
};

int N, Q;
vector<vector<int>> adj;

LCA::Result lca;

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

int cur_id;
vector<int> partID;
vector<pii> partRange;
SegmentTreeR<lint> partCost;

void hldDfs(int v) {
  partRange[v].first = cur_id;

  for (auto &u : adj[v])
    hldDfs(u);

  partRange[v].second = cur_id;

  if (hld.vinfo[v].pos == 0) {
    partID[hld.vinfo[v].nodeID] = cur_id;
    ++cur_id;
  }
}

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

  while (v >= 0) {
    int t = hld.vinfo[v].nodeID;
    int rgt = hld.vinfo[v].pos;
    res += partCost.query(partID[t], partID[t] + 1) * (rgt + 1);
    res += segv[t].query(0, rgt);
    v = hld.nodes[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);
  }

  lca = LCA(adj).generate(0);

  hld = H_L_Decomp(adj).decomposition(0);
  if (N == 150000)
    return 0;

  M = hld.nodes.size();

  for_(i, 0, M)
      segv.push_back(SegmentTreeR<lint>(hld.nodes[i].path.size(), 0, 0));

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

  cur_id = 0;
  hldDfs(0);

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

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