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

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

#define dump(...) cout << "# " << #__VA_ARGS__ << '=' << (__VA_ARGS__) << endl
#define repi(i, a, b) for (int i = int(a); i < int(b); i++)
#define peri(i, a, b) for (int i = int(b); i-- > int(a);)
#define rep(i, n) repi(i, 0, n)
#define per(i, n) peri(i, 0, n)
#define all(c) begin(c), end(c)
#define mp make_pair
#define mt make_tuple

typedef unsigned int uint;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<double> vd;
typedef vector<vd> vvd;
typedef vector<string> vs;

constexpr ll INF = 1e18;
constexpr int MOD = 1e9 + 7;
constexpr double EPS = 1e-9;

template <typename T1, typename T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &p) {
  return os << '(' << p.first << ',' << p.second << ')';
}
template <typename Ostream, typename Container>
Ostream &operator<<(Ostream &os, const Container &c) {
  os << '[';
  for (auto i = begin(c); i != end(c); ++i)
    os << (i == begin(c) ? "" : " ") << *i;
  return os << ']';
}

struct Edge {
  int src, dst;
  Edge() {}
  Edge(int s, int d) : src(s), dst(d) {}
};
typedef vector<vector<Edge>> Graph;

// int DFS1(const Graph& g,int p,int u,vi& sizes)
//{
//	for(auto e:g[u]) if(e.dst!=p)
//		sizes[u]+=DFS1(g,u,e.dst,sizes);
//	return sizes[u];
// }
// void DFS2(const Graph& g,int p,int u,const vi& sizes,vi& path,vvi& paths)
//{
//	path.push_back(u);
//	for(auto e:g[u]){
//		int v=e.dst;
//		if(v==p) continue;
//		if(sizes[v]*2>=sizes[u])
//			DFS2(g,u,v,sizes,path,paths);
//		else{
//			vi tmp;
//			DFS2(g,u,v,sizes,tmp,paths);
//		}
//	}
//	if(path[0]==u)
//		paths.push_back(path);
// }
vvi HeavyLightDecomposition(const Graph &g, int root = 0) {
  int n = g.size();
  vi sizes(n, 1);
  // DFS1(g,-1,root,sizes);
  {
    stack<pii> st;
    st.emplace(-1, root);
    vi vis(n);
    while (st.size()) {
      int p, u;
      tie(p, u) = st.top();
      if (!vis[u]) {
        vis[u] = 1;
        for (auto e : g[u])
          if (e.dst != p)
            st.emplace(u, e.dst);
      } else {
        for (auto e : g[u])
          if (e.dst != p)
            sizes[u] += sizes[e.dst];
        st.pop();
      }
    }
  }
  // vi path;
  // vvi paths;
  // DFS2(g,-1,root,sizes,path,paths);
  vvi paths(1);
  {
    stack<tuple<int, int, int>> st;
    st.emplace(-1, root, 0);
    vi vis(n);
    while (st.size()) {
      int p, u, i;
      tie(p, u, i) = st.top();
      if (!vis[u]) {
        paths[i].push_back(u);
        for (auto e : g[u])
          if (e.dst != p) {
            if (sizes[e.dst] * 2 >= sizes[u])
              st.emplace(u, e.dst, i);
            else {
              paths.push_back(vi());
              st.emplace(u, e.dst, paths.size() - 1);
            }
          }
        vis[u] = 1;
      } else {
        st.pop();
      }
    }
  }
  return paths;
}

vi GetParents(const Graph &g, int root = 0) {
  vi ps(g.size(), -1);
  queue<int> q;
  q.push(root);
  while (q.size()) {
    int u = q.front();
    q.pop();
    for (auto e : g[u])
      if (e.dst != ps[u]) {
        ps[e.dst] = u;
        q.push(e.dst);
      }
  }
  return ps;
}

struct LCA {
  vi ds;
  vvi ps;
  LCA(const Graph &g, int root = 0)
      : ds(g.size()), ps(32 - __builtin_clz(g.size()), vi(g.size(), -1)) {
    // DFS(g,-1,root,0);
    {
      stack<tuple<int, int, int>> st;
      st.emplace(-1, root, 0);
      while (st.size()) {
        int p, v, d;
        tie(p, v, d) = st.top();
        st.pop();
        ds[v] = d;
        ps[0][v] = p;
        for (auto e : g[v])
          if (e.dst != p)
            st.emplace(v, e.dst, d + 1);
      }
    }
    rep(i, ps.size() - 1) rep(j, ps[i].size()) ps[i + 1][j] =
        ps[i][j] == -1 ? -1 : ps[i][ps[i][j]];
  }
  // void DFS(const Graph& g,int p,int v,int d){
  //	ds[v]=d;
  //	ps[0][v]=p;
  //	for(auto e:g[v]) if(e.dst!=p)
  //		DFS(g,e.src,e.dst,d+1);
  // }
  int Find(int u, int v) {
    if (ds[u] > ds[v])
      swap(u, v);
    rep(i, ps.size()) if ((ds[v] - ds[u]) >> i & 1) v = ps[i][v];
    if (u == v)
      return u;
    per(i, ps.size()) if (ps[i][u] != ps[i][v]) u = ps[i][u], v = ps[i][v];
    return ps[0][u];
  }
};

int NextPow2(int x) {
  x--;
  for (int i = 1; i < 32; i *= 2)
    x |= x >> i;
  return x + 1;
}

struct SegmentTree {
  int size;
  vl sums, maxs, lmaxs, rmaxs, props;
  vi flags;
  SegmentTree(int n)
      : size(NextPow2(n)), sums(size * 2), maxs(size * 2, -INF),
        lmaxs(size * 2, -INF), rmaxs(size * 2, -INF), props(size * 2),
        flags(size * 2) {}
  void Update(int ql, int qr, ll x) { Update(ql, qr, x, 1, 0, size); }
  tuple<ll, ll, ll, ll> Query(int ql, int qr) {
    return Query(ql, qr, 1, 0, size);
  }

  void Propagate(int i) {
    if (!flags[i])
      return;
    flags[i] = 0;
    if (i < size) {
      props[i * 2] = props[i * 2 + 1] = props[i];
      flags[i * 2] = flags[i * 2 + 1] = 1;
      rep(j, 2) {
        props[i * 2 + j] = props[i];
        flags[i * 2 + j] = 1;
        sums[i * 2 + j] = sums[i] / 2;
        maxs[i * 2 + j] = lmaxs[i * 2 + j] = rmaxs[i * 2 + j] =
            max(sums[i * 2 + j], props[i]);
      }
    }
  }
  void Update(int ql, int qr, ll x, int i, int l, int r) {
    if (qr <= l || r <= ql)
      return;
    if (ql <= l && r <= qr) {
      props[i] = x;
      flags[i] = 1;
      sums[i] = x * (r - l);
      maxs[i] = lmaxs[i] = rmaxs[i] = max(sums[i], x);
      return;
    }
    Propagate(i);
    Update(ql, qr, x, i * 2, l, (l + r) / 2);
    Update(ql, qr, x, i * 2 + 1, (l + r) / 2, r);
    sums[i] = sums[i * 2] + sums[i * 2 + 1];
    maxs[i] =
        max({maxs[i * 2], maxs[i * 2 + 1], rmaxs[i * 2] + lmaxs[i * 2 + 1]});
    lmaxs[i] = max(lmaxs[i * 2], sums[i * 2] + lmaxs[i * 2 + 1]);
    rmaxs[i] = max(rmaxs[i * 2 + 1], rmaxs[i * 2] + sums[i * 2 + 1]);
  }
  tuple<ll, ll, ll, ll> Query(int ql, int qr, int i, int l, int r) {
    if (qr <= l || r <= ql)
      return mt(0, -INF, -INF, -INF);
    if (ql <= l && r <= qr)
      return mt(sums[i], maxs[i], lmaxs[i], rmaxs[i]);
    Propagate(i);
    ll s1, m1, l1, r1;
    tie(s1, m1, l1, r1) = Query(ql, qr, i * 2, l, (l + r) / 2);
    ll s2, m2, l2, r2;
    tie(s2, m2, l2, r2) = Query(ql, qr, i * 2 + 1, (l + r) / 2, r);
    return mt(s1 + s2, max({m1, m2, r1 + l2}), max(l1, s1 + l2),
              max(r2, r1 + s2));
  }
};

int main() {
  for (int n, q; cin >> n >> q && n | q;) {
    vi ws(n);
    rep(i, n) cin >> ws[i];
    Graph g(n);
    rep(i, n - 1) {
      int u, v;
      cin >> u >> v;
      u--, v--;
      g[u].emplace_back(u, v);
      g[v].emplace_back(v, u);
    }

    vvi paths = HeavyLightDecomposition(g);
    vi parents = GetParents(g);
    vi is(n), js(n);
    rep(i, paths.size()) rep(j, paths[i].size()) is[paths[i][j]] = i,
                                                 js[paths[i][j]] = j;

    vector<SegmentTree> sts;
    for (const auto &path : paths) {
      int size = path.size();
      SegmentTree st(size);
      rep(i, size) st.Update(i, i + 1, ws[path[i]]);
      sts.push_back(st);
    }

    LCA lca(g);

    rep(_, q) {
      int t, u, v, x;
      cin >> t >> u >> v >> x;
      u--, v--;
      int a = lca.Find(u, v);
      if (t == 1) { // update
        for (;;) {
          int left = is[u] == is[a] ? js[a] : 0;
          sts[is[u]].Update(left, js[u] + 1, x);
          if (is[u] == is[a])
            break;
          else
            u = parents[paths[is[u]][0]];
        }
        for (;;) {
          int left = is[v] == is[a] ? js[a] + 1 : 0;
          sts[is[v]].Update(left, js[v] + 1, x);
          if (is[v] == is[a])
            break;
          else
            v = parents[paths[is[v]][0]];
        }
      } else { // query
        ll m1 = -INF, l1 = -INF;
        for (;;) {
          int left = is[u] == is[a] ? js[a] : 0;
          ll s, m, l, r;
          tie(s, m, l, r) = sts[is[u]].Query(left, js[u] + 1);
          tie(m1, l1) = mt(max({m, m1, r + l1}), max(l, s + l1));
          if (is[u] == is[a])
            break;
          else
            u = parents[paths[is[u]][0]];
        }
        ll m2 = -INF, l2 = -INF;
        for (;;) {
          int left = is[v] == is[a] ? js[a] + 1 : 0;
          ll s, m, l, r;
          tie(s, m, l, r) = sts[is[v]].Query(left, js[v] + 1);
          tie(m2, l2) = mt(max({m, m2, r + l2}), max(l, s + l2));
          if (is[v] == is[a])
            break;
          else
            v = parents[paths[is[v]][0]];
        }
        cout << max({m1, m2, l1 + l2}) << endl;
      }
    }
  }
}

Error: 0

Fixed submission:

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

#define dump(...) cout << "# " << #__VA_ARGS__ << '=' << (__VA_ARGS__) << endl
#define repi(i, a, b) for (int i = int(a); i < int(b); i++)
#define peri(i, a, b) for (int i = int(b); i-- > int(a);)
#define rep(i, n) repi(i, 0, n)
#define per(i, n) peri(i, 0, n)
#define all(c) begin(c), end(c)
#define mp make_pair
#define mt make_tuple

typedef unsigned int uint;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<double> vd;
typedef vector<vd> vvd;
typedef vector<string> vs;

constexpr ll INF = 1e18;
constexpr int MOD = 1e9 + 7;
constexpr double EPS = 1e-9;

template <typename T1, typename T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &p) {
  return os << '(' << p.first << ',' << p.second << ')';
}
template <typename Ostream, typename Container>
Ostream &operator<<(Ostream &os, const Container &c) {
  os << '[';
  for (auto i = begin(c); i != end(c); ++i)
    os << (i == begin(c) ? "" : " ") << *i;
  return os << ']';
}

struct Edge {
  int src, dst;
  Edge() {}
  Edge(int s, int d) : src(s), dst(d) {}
};
typedef vector<vector<Edge>> Graph;

int DFS1(const Graph &g, int p, int u, vi &sizes) {
  for (auto e : g[u])
    if (e.dst != p)
      sizes[u] += DFS1(g, u, e.dst, sizes);
  return sizes[u];
}
void DFS2(const Graph &g, int p, int u, const vi &sizes, vi &path, vvi &paths) {
  path.push_back(u);
  for (auto e : g[u]) {
    int v = e.dst;
    if (v == p)
      continue;
    if (sizes[v] * 2 >= sizes[u])
      DFS2(g, u, v, sizes, path, paths);
    else {
      vi tmp;
      DFS2(g, u, v, sizes, tmp, paths);
    }
  }
  if (path[0] == u)
    paths.push_back(path);
}
vvi HeavyLightDecomposition(const Graph &g, int root = 0) {
  int n = g.size();
  vi sizes(n, 1);
  DFS1(g, -1, root, sizes);
  vi path;
  vvi paths;
  DFS2(g, -1, root, sizes, path, paths);
  return paths;
}

vi GetParents(const Graph &g, int root = 0) {
  vi ps(g.size(), -1);
  queue<int> q;
  q.push(root);
  while (q.size()) {
    int u = q.front();
    q.pop();
    for (auto e : g[u])
      if (e.dst != ps[u]) {
        ps[e.dst] = u;
        q.push(e.dst);
      }
  }
  return ps;
}

struct LCA {
  vi ds;
  vvi ps;
  LCA(const Graph &g, int root = 0)
      : ds(g.size()), ps(32 - __builtin_clz(g.size()), vi(g.size(), -1)) {
    DFS(g, -1, root, 0);
    rep(i, ps.size() - 1) rep(j, ps[i].size()) ps[i + 1][j] =
        ps[i][j] == -1 ? -1 : ps[i][ps[i][j]];
  }
  void DFS(const Graph &g, int p, int v, int d) {
    ds[v] = d;
    ps[0][v] = p;
    for (auto e : g[v])
      if (e.dst != p)
        DFS(g, e.src, e.dst, d + 1);
  }
  int Find(int u, int v) {
    if (ds[u] > ds[v])
      swap(u, v);
    rep(i, ps.size()) if ((ds[v] - ds[u]) >> i & 1) v = ps[i][v];
    if (u == v)
      return u;
    per(i, ps.size()) if (ps[i][u] != ps[i][v]) u = ps[i][u], v = ps[i][v];
    return ps[0][u];
  }
};

int NextPow2(int x) {
  x--;
  for (int i = 1; i < 32; i *= 2)
    x |= x >> i;
  return x + 1;
}

struct SegmentTree {
  int size;
  vl sums, maxs, lmaxs, rmaxs, props;
  vi flags;
  SegmentTree(int n)
      : size(NextPow2(n)), sums(size * 2), maxs(size * 2, -INF),
        lmaxs(size * 2, -INF), rmaxs(size * 2, -INF), props(size * 2),
        flags(size * 2) {}
  void Update(int ql, int qr, ll x) { Update(ql, qr, x, 1, 0, size); }
  tuple<ll, ll, ll, ll> Query(int ql, int qr) {
    return Query(ql, qr, 1, 0, size);
  }

  void Propagate(int i) {
    if (!flags[i])
      return;
    flags[i] = 0;
    if (i < size) {
      props[i * 2] = props[i * 2 + 1] = props[i];
      flags[i * 2] = flags[i * 2 + 1] = 1;
      rep(j, 2) {
        props[i * 2 + j] = props[i];
        flags[i * 2 + j] = 1;
        sums[i * 2 + j] = sums[i] / 2;
        maxs[i * 2 + j] = lmaxs[i * 2 + j] = rmaxs[i * 2 + j] =
            max(sums[i * 2 + j], props[i]);
      }
    }
  }
  void Update(int ql, int qr, ll x, int i, int l, int r) {
    if (qr <= l || r <= ql)
      return;
    if (ql <= l && r <= qr) {
      props[i] = x;
      flags[i] = 1;
      sums[i] = x * (r - l);
      maxs[i] = lmaxs[i] = rmaxs[i] = max(sums[i], x);
      return;
    }
    Propagate(i);
    Update(ql, qr, x, i * 2, l, (l + r) / 2);
    Update(ql, qr, x, i * 2 + 1, (l + r) / 2, r);
    sums[i] = sums[i * 2] + sums[i * 2 + 1];
    maxs[i] =
        max({maxs[i * 2], maxs[i * 2 + 1], rmaxs[i * 2] + lmaxs[i * 2 + 1]});
    lmaxs[i] = max(lmaxs[i * 2], sums[i * 2] + lmaxs[i * 2 + 1]);
    rmaxs[i] = max(rmaxs[i * 2 + 1], rmaxs[i * 2] + sums[i * 2 + 1]);
  }
  tuple<ll, ll, ll, ll> Query(int ql, int qr, int i, int l, int r) {
    if (qr <= l || r <= ql)
      return mt(0, -INF, -INF, -INF);
    if (ql <= l && r <= qr)
      return mt(sums[i], maxs[i], lmaxs[i], rmaxs[i]);
    Propagate(i);
    ll s1, m1, l1, r1;
    tie(s1, m1, l1, r1) = Query(ql, qr, i * 2, l, (l + r) / 2);
    ll s2, m2, l2, r2;
    tie(s2, m2, l2, r2) = Query(ql, qr, i * 2 + 1, (l + r) / 2, r);
    return mt(s1 + s2, max({m1, m2, r1 + l2}), max(l1, s1 + l2),
              max(r2, r1 + s2));
  }
};

int main() {
  for (int n, q; cin >> n >> q && n | q;) {
    vi ws(n);
    rep(i, n) cin >> ws[i];
    Graph g(n);
    rep(i, n - 1) {
      int u, v;
      cin >> u >> v;
      u--, v--;
      g[u].emplace_back(u, v);
      g[v].emplace_back(v, u);
    }

    vvi paths = HeavyLightDecomposition(g);
    vi parents = GetParents(g);
    vi is(n), js(n);
    rep(i, paths.size()) rep(j, paths[i].size()) is[paths[i][j]] = i,
                                                 js[paths[i][j]] = j;

    vector<SegmentTree> sts;
    for (const auto &path : paths) {
      int size = path.size();
      SegmentTree st(size);
      rep(i, size) st.Update(i, i + 1, ws[path[i]]);
      sts.push_back(st);
    }

    LCA lca(g);

    rep(_, q) {
      int t, u, v, x;
      cin >> t >> u >> v >> x;
      u--, v--;
      int a = lca.Find(u, v);
      if (t == 1) { // update
        for (;;) {
          int left = is[u] == is[a] ? js[a] : 0;
          sts[is[u]].Update(left, js[u] + 1, x);
          if (is[u] == is[a])
            break;
          else
            u = parents[paths[is[u]][0]];
        }
        for (;;) {
          int left = is[v] == is[a] ? js[a] + 1 : 0;
          sts[is[v]].Update(left, js[v] + 1, x);
          if (is[v] == is[a])
            break;
          else
            v = parents[paths[is[v]][0]];
        }
      } else { // query
        ll m1 = -INF, l1 = -INF;
        for (;;) {
          int left = is[u] == is[a] ? js[a] : 0;
          ll s, m, l, r;
          tie(s, m, l, r) = sts[is[u]].Query(left, js[u] + 1);
          tie(m1, l1) = mt(max({m, m1, r + l1}), max(l, s + l1));
          if (is[u] == is[a])
            break;
          else
            u = parents[paths[is[u]][0]];
        }
        ll m2 = -INF, l2 = -INF;
        for (;;) {
          int left = is[v] == is[a] ? js[a] + 1 : 0;
          ll s, m, l, r;
          tie(s, m, l, r) = sts[is[v]].Query(left, js[v] + 1);
          tie(m2, l2) = mt(max({m, m2, r + l2}), max(l, s + l2));
          if (is[v] == is[a])
            break;
          else
            v = parents[paths[is[v]][0]];
        }
        cout << max({m1, m2, l1 + l2}) << endl;
      }
    }
  }
}