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

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

#define int long long

typedef pair<int, int> pint;
typedef vector<int> vint;
#define pb push_back
#define mp make_pair
#define rep(i, n) for (int i = 0; i < (n); i++)
template <class T, class U> void chmin(T &t, U f) {
  if (t > f)
    t = f;
}
template <class T, class U> void chmax(T &t, U f) {
  if (t < f)
    t = f;
}

struct segtree {
  vint dat, lazy;
  int N;

  void init(int n) {
    N = 1;
    while (N < n)
      N *= 2;
    dat.assign(N * 2, 0);
    lazy.assign(N * 2, 0);
  }

  inline void evaluate(int k, int l, int r) {
    dat[k] += (r - l) * lazy[k];
    if (k < N - 1) {
      lazy[k * 2 + 1] += lazy[k];
      lazy[k * 2 + 2] += lazy[k];
    }
    lazy[k] = 0;
  }

  inline void update(int k) { dat[k] = dat[k * 2 + 1] + dat[k * 2 + 2]; }

  void add(int a, int b, int x) { add(a, b, x, 0, 0, N); }
  void add(int a, int b, int x, int k, int l, int r) {
    evaluate(k, l, r);
    if (r <= a || b <= l)
      return;
    if (a <= l && r <= b) {
      lazy[k] += x;
      evaluate(k, l, r);
      return;
    }
    add(a, b, x, k * 2 + 1, l, (l + r) / 2);
    add(a, b, x, k * 2 + 2, (l + r) / 2, r);
    update(k);
  }

  int get(int a, int b) { return get(a, b, 0, 0, N); }
  int get(int a, int b, int k, int l, int r) {
    evaluate(k, l, r);
    if (r <= a || b <= l)
      return 0;
    if (a <= l && r <= b)
      return dat[k];
    return get(a, b, k * 2 + 1, l, (l + r) / 2) +
           get(a, b, k * 2 + 2, (l + r) / 2, r);
  }
};

struct HLD {
  int N;
  vint par, depth, heavy, treesize, chain, head;
  vector<segtree> seg;
  void init(vector<vint> &G) {
    N = G.size();
    par = depth = heavy = treesize = chain = head = vint(N);
    seg.clear();
    dfs(G);
  }

  void dfs(vector<vint> &G) {
    vint stk;
    stk.pb(0);
    par[0] = -1;
    depth[0] = 0;
    rep(i, N) {
      int v = stk[i];
      rep(j, G[v].size()) {
        int to = G[v][j];
        if (to == par[v])
          continue;
        stk.pb(to);
        par[to] = v;
        depth[to] = depth[v] + 1;
      }
    }
    for (int i = N - 1; i >= 0; i--) {
      int v = stk[i];
      int ma = 0;
      treesize[v] = 1;
      heavy[v] = -1;

      rep(j, G[v].size()) {
        int to = G[v][j];
        if (to == par[v])
          continue;
        if (treesize[to] > ma) {
          ma = treesize[to];
          heavy[v] = to;
        }
        treesize[v] += treesize[to];
      }
    }
    rep(i, N) {
      if (par[i] >= 0 && heavy[par[i]] == i)
        continue;
      int cnt = 0;
      for (int j = i; ~j; j = heavy[j]) {
        head[j] = i;
        chain[j] = seg.size();
        cnt++;
      }
      seg.pb(segtree());
      seg.back().init(cnt);
    }
  }

  int lca(int u, int v) {
    while (chain[u] != chain[v]) {
      if (depth[head[u]] < depth[head[v]])
        swap(u, v);
      u = par[head[u]];
    }
    return depth[u] < depth[v] ? u : v;
  }

  int dist(int u) {
    int x = u;
    int ret = 0;
    while (~u) {
      ret += seg[chain[u]].get(0, depth[u] - depth[head[u]]);
      int p = par[head[u]];
      if (~p)
        ret += seg[chain[p]].get(depth[p] - depth[head[p]],
                                 depth[p] - depth[head[p]] + 1) *
               (depth[x] - depth[p]);
      u = p;
    }
    return ret;
  }

  void addquery(int u, int x) {
    seg[chain[u]].add(depth[u] - depth[head[u]], seg[chain[u]].N, x);
  }

  int getquery(int u, int v) {
    int p = lca(u, v);
    return dist(u) + dist(v) - 2 * dist(p);
  }
};

int N, Q;
vector<vint> G;
HLD hld;

signed main() {
  scanf("%lld%lld", &N, &Q);
  G.resize(N);
  rep(i, N - 1) {
    int a, b;
    scanf("%lld%lld", &a, &b);
    G[a].pb(b);
    G[b].pb(a);
  }

  hld.init(G);

  while (Q--) {
    int type;
    scanf("%lld", &type);
    if (type == 0) {
      int u, v;
      scanf("%lld%lld", &u, &v);
      int p = hld.lca(u, v);
      printf("%lld\\n", hld.getquery(u, v));
    } else {
      int u, x;
      scanf("%lld%lld", &u, &x);
      hld.addquery(u, x);
    }
  }
  return 0;
}

/*
9 6
0 1
0 2
0 3
1 4
1 5
4 6
5 7
5 8
1 0 1
1 1 2
0 6 3
1 5 5
1 8 4
0 4 3

*/

Error: 0

Fixed submission:

#include <bits/stdc++.h>
using namespace std;
#define int long long
struct seg_tree {
  int N;
  vector<int> xv, yv, xc, yc, lz;
  void init(int n, int *v) {
    N = 1;
    while (n > N)
      N *= 2;
    xv.resize(N * 2 - 1, 0);
    yv.resize(N * 2 - 1, 0);
    xc.resize(N * 2 - 1, 0);
    yc.resize(N * 2 - 1, 0);
    lz.resize(N * 2 - 1, 0);

    for (int i = 0; i < n - 1; i++) {
      if (v[i] < v[i + 1])
        xc[i + N - 1]++;

      else
        yc[i + N - 1]++;
    }
    for (int i = N - 2; i >= 0; i--)
      update(i);
  }
  inline void evaluate(int k) {
    if (k < 0)
      for (;;)
        ;
    xv[k] += xc[k] * lz[k];
    yv[k] -= yc[k] * lz[k];
    if (k < N - 1) {
      if (k * 2 + 2 >= N * 2 - 1)
        for (;;)
          ;
      lz[k * 2 + 1] += lz[k];
      lz[k * 2 + 2] += lz[k];
    }
    lz[k] = 0;
  }
  inline void update(int k) {
    if (k < 0)
      for (;;)
        ;
    xv[k] = xv[k * 2 + 1] + xv[k * 2 + 2];
    yv[k] = yv[k * 2 + 1] + yv[k * 2 + 2];
    xc[k] = xc[k * 2 + 1] + xc[k * 2 + 2];
    yc[k] = yc[k * 2 + 1] + yc[k * 2 + 2];
  }
  void add(int a, int b, int x) { add(a, b, x, 0, 0, N); }
  void add(int a, int b, int x, int k, int l, int r) {
    if (a < 0 || b < 0 || k < 0 || l < 0 || r < 0)
      for (;;)
        ;
    evaluate(k);
    if (r <= a || b <= l)
      return;
    if (a <= l && r <= b) {
      lz[k] += x;
      evaluate(k);
      return;
    }
    add(a, b, x, k * 2 + 1, l, (l + r) / 2);
    add(a, b, x, k * 2 + 2, (l + r) / 2, r);
    update(k);
  }
  int getSum(int a, int b) { return getSum(a, b, 0, 0, N); }
  int getSum(int a, int b, int k, int l, int r) {
    if (a < 0 || b < 0 || k < 0 || l < 0 || r < 0)
      for (;;)
        ;
    evaluate(k);
    if (r <= a || b <= l)
      return 0;
    if (a <= l && r <= b)
      return xv[k] + yv[k];
    int vl = getSum(a, b, k * 2 + 1, l, (l + r) / 2);
    int vr = getSum(a, b, k * 2 + 2, (l + r) / 2, r);
    return vl + vr;
  }
};

int N, Q;
vector<int> G[150010];

int vs[300010], in[150010], out[150010], depth[150010], par[20][150010];
seg_tree seg;
void dfs(int v, int p, int d, int &k) {
  vs[k] = v;
  in[v] = out[v] = k;
  par[0][v] = p;
  depth[v] = d;
  k++;
  for (int i = 0; i < G[v].size(); i++) {
    int to = G[v][i];
    if (to == p)
      continue;
    dfs(to, v, d + 1, k);
    vs[k] = v;
    out[v] = k;
    k++;
  }
}

void init() {
  int k = 0;
  memset(in, -1, sizeof(in));
  memset(out, -1, sizeof(out));
  memset(depth, -1, sizeof(depth));
  dfs(0, -1, 0, k);
  seg.init(N * 2 - 1, vs);

  for (int i = 0; i < 19; i++) {
    for (int j = 0; j < N; j++) {
      if (par[i][j] < 0)
        par[i + 1][j] = -1;
      else
        par[i + 1][j] = par[i][par[i][j]];
    }
  }

  for (int i = 0; i < N; i++) {
    if (in[i] == -1 || out[i] == -1 || depth[i] == -1)
      for (;;)
        ;
  }
}

int lca(int u, int v) {
  if (depth[v] < depth[u])
    swap(v, u);
  for (int i = 0; i < 20; i++) {
    if ((depth[v] - depth[u]) >> i & 1) {
      v = par[i][v];
    }
  }
  if (v == u)
    return v;
  for (int i = 19; i >= 0; i--) {
    if (par[i][v] != par[i][u]) {
      v = par[i][v];
      u = par[i][u];
    }
  }
  return par[0][v];
}

signed main() {
  scanf("%lld%lld", &N, &Q);
  for (int i = 0; i < N - 1; i++) {
    int a, b;
    scanf("%lld%lld", &a, &b);
    G[a].push_back(b);
    G[b].push_back(a);
  }

  init();
  while (Q--) {
    int type, a, b;
    scanf("%lld%lld%lld", &type, &a, &b);
    if (type == 0) {
      int p = lca(a, b);
      if (p < 0)
        for (;;)
          ;
      if (in[a] < 0 || out[a] < 0 || in[b] < 0 || out[b] < 0 || in[p] < 0 ||
          out[p] < 0)
        for (;;)
          ;
      int x = seg.getSum(0, in[a]);
      int y = seg.getSum(0, in[b]);
      int z = seg.getSum(0, in[p]);
      printf("%lld\\n", x + y - 2 * z);
    } else {
      if (in[a] < 0 || out[a] < 0)
        for (;;)
          ;
      seg.add(in[a], out[a], b);
    }
  }

  return 0;
}