Problem p01564 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>

using namespace std;

#define int long long
#define all(v) begin(v), end(v)
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define reps(i, s, n) for (int i = (int)(s); i < (int)(n); i++)
#define min(...) min({__VA_ARGS__})
#define max(...) max({__VA_ARGS__})

const int inf = 1LL << 55;
const int mod = 1e9 + 7;

struct HLDT {
  vector<vector<int>> graph;
  // vid:????§£????????????????????????????????§?????£?¶????
  vector<int> vid, head, heavy, par, depth, inv;

  HLDT() {}
  HLDT(int n)
      : graph(n), vid(n, -1), head(n), heavy(n, -1), par(n), depth(n), inv(n) {}

  void add_edge(int u, int v) {
    graph[u].push_back(v);
    graph[v].push_back(u);
  }

  void build() {
    dfs(0, -1);
    bfs();
  }

  int dfs(int u, int p) {
    par[u] = p;
    int subsz = 1, max_chsz = 0;
    for (int v : graph[u]) {
      if (v == p)
        continue;
      depth[v] = depth[u] + 1;
      int chsz = dfs(v, u);
      subsz += chsz;
      if (max_chsz < chsz)
        max_chsz = chsz, heavy[u] = v;
    }
    return subsz;
  }

  void bfs() {
    int id = 0;
    queue<int> que; // ????§£?????????????????????
    que.push(0);
    while (!que.empty()) {
      int h = que.front();
      que.pop();
      for (int i = h; i != -1;
           i = heavy[i]) { // ????????????Heavy
                           // edge????????£?????????????????????
        vid[i] = id++;
        inv[vid[i]] = i;
        head[i] = h;
        for (int j : graph[i]) {
          if (j != par[i] && j != heavy[i])
            que.push(j);
        }
      }
    }
  }

  void for_each(int u, int v, vector<tuple<int, int, bool>> &lr) {
    if (vid[u] < vid[v]) {
      lr.emplace_back(max(vid[head[v]], vid[u]), vid[v], true); // ?????????
      if (head[u] != head[v])
        for_each(u, par[head[v]], lr);
    } else { // ??????????????????????????§????????????????????§????????????????????????
      lr.emplace_back(max(vid[head[u]], vid[v]), vid[u], false); // ?????????
      if (head[u] != head[v])
        for_each(par[head[u]], v, lr);
    }
  }

  int lca(int u, int v) {
    if (vid[u] > vid[v])
      swap(u, v);
    if (head[u] == head[v])
      return u;
    return lca(u, par[head[v]]);
  }

  int distance(int u, int v) {
    return depth[u] + depth[v] - 2 * depth[lca(u, v)];
  }
};

struct State {
  int sum, mxs, lmxs, rmxs;
  State() : sum(0), mxs(-inf), lmxs(-inf), rmxs(-inf) {}
  State(int sum, int mxs, int lmxs, int rmxs)
      : sum(sum), mxs(mxs), lmxs(lmxs), rmxs(rmxs) {}
  State(int c, int sz) {
    int d = (c > 0 ? c * sz : c);
    sum = c * sz, mxs = lmxs = rmxs = d;
  }
  State operator+(State s) {
    State res;
    res.sum = sum + s.sum;
    res.mxs = max(mxs, s.mxs, rmxs + s.lmxs);
    res.lmxs = max(lmxs, sum + s.lmxs);
    res.rmxs = max(rmxs + s.sum, s.rmxs);
    return res;
  }
  State operator~() {
    State res = *this;
    swap(res.lmxs, res.rmxs);
    return res;
  }
};

// Lazy-evaluated Segment Tree
struct SegmentTree {
  vector<State> sum;
  vector<int> lazy;
  int sz;
  SegmentTree() {}
  SegmentTree(int n) {
    sz = 1;
    while (sz < n)
      sz *= 2;
    sum.resize(2 * sz - 1, State());
    lazy.resize(2 * sz - 1, -inf);
  }
  inline void lazy_evaluate(int k, int l, int r) {
    if (lazy[k] == -inf)
      return;
    sum[k] = State(lazy[k], r - l);
    if (k < sz) {
      lazy[2 * k + 1] = lazy[k];
      lazy[2 * k + 2] = lazy[k];
    }
    lazy[k] = -inf;
  }
  void update(int a, int b, int x, int k, int l, int r) {
    lazy_evaluate(k, l, r);
    if (r <= a || b <= l)
      return;
    if (a <= l && r <= b) {
      lazy[k] = x;
      lazy_evaluate(k, l, r);
      return;
    }
    update(a, b, x, 2 * k + 1, l, (l + r) / 2);
    update(a, b, x, 2 * k + 2, (l + r) / 2, r);
    sum[k] = sum[2 * k + 1] + sum[2 * k + 2];
  }
  void update(int a, int b, int x) { update(a, b, x, 0, 0, sz); }
  State query(int a, int b, int k, int l, int r) {
    lazy_evaluate(k, l, r);
    if (r <= a || b <= l)
      return State();
    if (a <= l && r <= b)
      return sum[k];
    return query(a, b, 2 * k + 1, l, (l + r) / 2) +
           query(a, b, 2 * k + 2, (l + r) / 2, r);
  }
  State query(int a, int b) { return query(a, b, 0, 0, sz); }
};

int n, q;
vector<int> w;
HLDT hldt;
SegmentTree seg;

signed main() {
  cin.tie(0);
  ios_base::sync_with_stdio(0);
  cout << fixed << setprecision(12);

  cin >> n >> q;
  w.resize(n);
  hldt = HLDT(n);
  seg = SegmentTree(n);
  rep(i, n) cin >> w[i];
  rep(i, n - 1) {
    int s, e;
    cin >> s >> e;
    --s, --e;
    hldt.add_edge(s, e);
  }
  hldt.build();
  rep(i, n) {
    vector<tuple<int, int, bool>> lr;
    hldt.for_each(i, i, lr);
    for (auto p : lr) {
      int x, y;
      bool z;
      tie(x, y, z) = p;
      seg.update(x, y + 1, w[i]);
    }
  }

  rep(i, q) {
    int t, a, b, c;
    cin >> t >> a >> b >> c;
    --a, --b;
    vector<tuple<int, int, bool>> lr;
    hldt.for_each(a, b, lr);
    if (t == 1) {
      for (auto p : lr) {
        int x, y;
        bool z;
        tie(x, y, z) = p;
        seg.update(x, y + 1, c);
      }
    } else if (t == 2) {
      State ds, us;
      for (auto p : lr) {
        int x, y;
        bool z;
        tie(x, y, z) = p;
        if (z)
          ds = seg.query(x, y + 1) + ds;
        else
          us = seg.query(x, y + 1) + us;
      }
      cout << (~us + ds).mxs << endl;
    }
  }

  return 0;
}

Fixed submission:
#include <bits/stdc++.h>

using namespace std;

#define int long long
#define all(v) begin(v), end(v)
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define reps(i, s, n) for (int i = (int)(s); i < (int)(n); i++)
#define min(...) min({__VA_ARGS__})
#define max(...) max({__VA_ARGS__})

const int inf = 1LL << 55;
const int mod = 1e9 + 7;

struct HLDT {
  vector<vector<int>> graph;
  // vid:????§£????????????????????????????????§?????£?¶????
  vector<int> vid, head, heavy, par, depth, inv;

  HLDT() {}
  HLDT(int n)
      : graph(n), vid(n, -1), head(n), heavy(n, -1), par(n), depth(n), inv(n) {}

  void add_edge(int u, int v) {
    graph[u].push_back(v);
    graph[v].push_back(u);
  }

  void build() {
    dfs(0, -1);
    bfs();
  }

  int dfs(int u, int p) {
    par[u] = p;
    int subsz = 1, max_chsz = 0;
    for (int v : graph[u]) {
      if (v == p)
        continue;
      depth[v] = depth[u] + 1;
      int chsz = dfs(v, u);
      subsz += chsz;
      if (max_chsz < chsz)
        max_chsz = chsz, heavy[u] = v;
    }
    return subsz;
  }

  void bfs() {
    int id = 0;
    queue<int> que; // ????§£?????????????????????
    que.push(0);
    while (!que.empty()) {
      int h = que.front();
      que.pop();
      for (int i = h; i != -1;
           i = heavy[i]) { // ????????????Heavy
                           // edge????????£?????????????????????
        vid[i] = id++;
        inv[vid[i]] = i;
        head[i] = h;
        for (int j : graph[i]) {
          if (j != par[i] && j != heavy[i])
            que.push(j);
        }
      }
    }
  }

  void for_each(int u, int v, vector<tuple<int, int, bool>> &lr) {
    if (vid[u] < vid[v]) {
      lr.emplace_back(max(vid[head[v]], vid[u]), vid[v], true); // ?????????
      if (head[u] != head[v])
        for_each(u, par[head[v]], lr);
    } else { // ??????????????????????????§????????????????????§????????????????????????
      lr.emplace_back(max(vid[head[u]], vid[v]), vid[u], false); // ?????????
      if (head[u] != head[v])
        for_each(par[head[u]], v, lr);
    }
  }

  int lca(int u, int v) {
    if (vid[u] > vid[v])
      swap(u, v);
    if (head[u] == head[v])
      return u;
    return lca(u, par[head[v]]);
  }

  int distance(int u, int v) {
    return depth[u] + depth[v] - 2 * depth[lca(u, v)];
  }
};

struct State {
  int sum, mxs, lmxs, rmxs;
  State() : sum(0), mxs(-inf), lmxs(-inf), rmxs(-inf) {}
  State(int sum, int mxs, int lmxs, int rmxs)
      : sum(sum), mxs(mxs), lmxs(lmxs), rmxs(rmxs) {}
  State(int c, int sz) {
    int d = (c > 0 ? c * sz : c);
    sum = c * sz, mxs = lmxs = rmxs = d;
  }
  State operator+(State s) {
    State res;
    res.sum = sum + s.sum;
    res.mxs = max(mxs, s.mxs, rmxs + s.lmxs);
    res.lmxs = max(lmxs, sum + s.lmxs);
    res.rmxs = max(rmxs + s.sum, s.rmxs);
    return res;
  }
  State operator~() {
    State res = *this;
    swap(res.lmxs, res.rmxs);
    return res;
  }
};

// Lazy-evaluated Segment Tree
struct SegmentTree {
  vector<State> sum;
  vector<int> lazy;
  int sz;
  SegmentTree() {}
  SegmentTree(int n) {
    sz = 1;
    while (sz < n)
      sz *= 2;
    sum.resize(2 * sz - 1, State());
    lazy.resize(2 * sz - 1, -inf);
  }
  inline void lazy_evaluate(int k, int l, int r) {
    if (lazy[k] == -inf)
      return;
    sum[k] = State(lazy[k], r - l);
    if (r - l > 1) {
      lazy[2 * k + 1] = lazy[k];
      lazy[2 * k + 2] = lazy[k];
    }
    lazy[k] = -inf;
  }
  void update(int a, int b, int x, int k, int l, int r) {
    lazy_evaluate(k, l, r);
    if (r <= a || b <= l)
      return;
    if (a <= l && r <= b) {
      lazy[k] = x;
      lazy_evaluate(k, l, r);
      return;
    }
    update(a, b, x, 2 * k + 1, l, (l + r) / 2);
    update(a, b, x, 2 * k + 2, (l + r) / 2, r);
    sum[k] = sum[2 * k + 1] + sum[2 * k + 2];
  }
  void update(int a, int b, int x) { update(a, b, x, 0, 0, sz); }
  State query(int a, int b, int k, int l, int r) {
    lazy_evaluate(k, l, r);
    if (r <= a || b <= l)
      return State();
    if (a <= l && r <= b)
      return sum[k];
    return query(a, b, 2 * k + 1, l, (l + r) / 2) +
           query(a, b, 2 * k + 2, (l + r) / 2, r);
  }
  State query(int a, int b) { return query(a, b, 0, 0, sz); }
};

int n, q;
vector<int> w;
HLDT hldt;
SegmentTree seg;

signed main() {
  cin.tie(0);
  ios_base::sync_with_stdio(0);
  cout << fixed << setprecision(12);

  cin >> n >> q;
  w.resize(n);
  hldt = HLDT(n);
  seg = SegmentTree(n);
  rep(i, n) cin >> w[i];
  rep(i, n - 1) {
    int s, e;
    cin >> s >> e;
    --s, --e;
    hldt.add_edge(s, e);
  }
  hldt.build();
  rep(i, n) {
    vector<tuple<int, int, bool>> lr;
    hldt.for_each(i, i, lr);
    for (auto p : lr) {
      int x, y;
      bool z;
      tie(x, y, z) = p;
      seg.update(x, y + 1, w[i]);
    }
  }

  rep(i, q) {
    int t, a, b, c;
    cin >> t >> a >> b >> c;
    --a, --b;
    vector<tuple<int, int, bool>> lr;
    hldt.for_each(a, b, lr);
    if (t == 1) {
      for (auto p : lr) {
        int x, y;
        bool z;
        tie(x, y, z) = p;
        seg.update(x, y + 1, c);
      }
    } else if (t == 2) {
      State ds, us;
      for (auto p : lr) {
        int x, y;
        bool z;
        tie(x, y, z) = p;
        if (z)
          ds = seg.query(x, y + 1) + ds;
        else
          us = seg.query(x, y + 1) + us;
      }
      cout << (~us + ds).mxs << endl;
    }
  }

  return 0;
}