Problem p02698 (C++) — buggy submission, verdict: Time Limit Exceeded

/**
  If comrades that you trust gather around you, hope can take physical form and
  become visible. That’s what I believe.
  */
#include <bits/stdc++.h>
using namespace std;
/**
  (▀̿Ĺ̯▀̿ ̿) (ง ͠° ͟ل͜ ͡°)ง
  */
const int N = 2e5 + 10;
int lazy[N << 2];
int t[N << 2];
int combine(int lhs, int rhs) { return max(lhs, rhs); }
auto build(int v, int l, int r) -> void {
  if (l == r) {
    t[v] = 0;
    lazy[v] = -1;
    return;
  }
  int mid = (l + r) >> 1;
  build(v << 1, l, mid);
  build(v << 1 | 1, mid + 1, r);
  t[v] = combine(t[v << 1], t[v << 1 | 1]);
}
auto push(int v, int l, int r) -> void {
  if (lazy[v] != -1) {
    t[v] = lazy[v];
    if (l < r) {
      lazy[v << 1] = lazy[v];
      lazy[(v << 1) ^ 1] = lazy[v];
    }
  }
  lazy[v] = -1;
}
void update(int v, int l, int r, int x, int y, int to_add) {
  push(v, l, r);
  if (l > y || r < x)
    return;
  if (l >= x && r <= y) {
    lazy[v] = to_add;
    push(v, l, r);
    return;
  }
  int mid = (l + r) >> 1;
  update(v << 1, l, mid, x, y, to_add);
  update((v << 1) ^ 1, mid + 1, r, x, y, to_add);
  t[v] = combine(t[v << 1], t[(v << 1) ^ 1]);
}

int get(int v, int l, int r, int x, int y) {
  if (l > y || r < x)
    return 0;
  push(v, l, r);
  if (l >= x && r <= y)
    return t[v];
  int mid = (l + r) >> 1;
  return combine(get(v << 1, l, mid, x, y),
                 get((v << 1) ^ 1, mid + 1, r, x, y));
}

int a[N];
int ans[N];
vector<int> g[N], vals[N];
int n;
map<int, int> to_val;
int MAX_T = -1;
auto dfs(int idx, int p = -1) -> void {
  auto nxt = to_val[a[idx]];
  ans[idx] = get(1, 1, MAX_T, 1, nxt - 1) + 1;
  update(1, 1, MAX_T, nxt, nxt, ans[idx]);
  vals[nxt].emplace_back(ans[idx]);
  for (auto &v : g[idx]) {
    if (v == p)
      continue;
    dfs(v, idx);
  }
  vals[nxt].pop_back();
  update(1, 1, MAX_T, nxt, nxt, vals[nxt].back());
}

auto dfs2(int idx, int p = -1) -> void {
  if (p != -1)
    ans[idx] = max(ans[idx], ans[p]);
  for (auto &v : g[idx]) {
    if (v == p)
      continue;
    dfs2(v, idx);
  }
}
auto main() -> int {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cin >> n;
  vector<int> tt;
  for (int i = 1; i <= n; ++i) {
    cin >> a[i];
    tt.emplace_back(a[i]);
  }
  for (int i = 1; i < n; ++i) {
    int u, v;
    cin >> u >> v;
    g[u].emplace_back(v);
    g[v].emplace_back(u);
  }
  sort(tt.begin(), tt.end());
  tt.erase(unique(tt.begin(), tt.end()), tt.end());

  for (int i = 0; i < tt.size(); ++i) {
    to_val[tt[i]] = i + 1;
  }
  MAX_T = tt.size() + 6;
  build(1, 1, MAX_T);
  for (int i = 1; i < MAX_T; ++i)
    vals[i].emplace_back(0);
  dfs(1);
  dfs2(1);
  for (int i = 1; i <= n; ++i)
    cout << ans[i] << '\\n';

  return 0;
}


Error: TLE

Fixed submission:

/**
  If comrades that you trust gather around you, hope can take physical form and
  become visible. That’s what I believe.
  */
#include <bits/stdc++.h>
using namespace std;
/**
  (▀̿Ĺ̯▀̿ ̿) (ง ͠° ͟ل͜ ͡°)ง
  */
const int N = 2e5 + 10;
class SegmentTreeMax {
private:
  int n;
  std::vector<int> t, a;

  void build(int v, int tl, int tr) {
    if (tl == tr) {
      t[v] = a[tl];
    } else {
      int tm = (tl + tr) / 2;
      build(v * 2, tl, tm);
      build(v * 2 + 1, tm + 1, tr);
      t[v] = max(t[v * 2], t[v * 2 + 1]);
    }
  }

  int get(int v, int tl, int tr, int l, int r) {
    if (l > r)
      return 0;
    if (l == tl && r == tr) {
      return t[v];
    }
    int tm = (tl + tr) / 2;
    return max(get(v * 2, tl, tm, l, min(r, tm)),
               get(v * 2 + 1, tm + 1, tr, max(l, tm + 1), r));
  }

  void update(int v, int tl, int tr, int pos, int new_val) {
    if (tl == tr) {
      t[v] = new_val;
    } else {
      int tm = (tl + tr) / 2;
      if (pos <= tm)
        update(v * 2, tl, tm, pos, new_val);
      else
        update(v * 2 + 1, tm + 1, tr, pos, new_val);
      t[v] = max(t[v * 2], t[v * 2 + 1]);
    }
  }

public:
  SegmentTreeMax(int _n) : n(_n) {
    t.assign(n * 4, 0);
    a.assign(n, 0);
  }

  SegmentTreeMax(std::vector<int> &_a) : n(_a.size()), a(_a) {
    t.assign(n * 4, 0);
    build(1, 1, n);
  }

  int get(int l, int r) { return get(1, 1, n, l, r); }

  void update(int pos, int val) { update(1, 1, n, pos, val); }
};
SegmentTreeMax tr(1);
int a[N];
int ans[N];
vector<int> g[N], vals[N];
int n;
map<int, int> to_val;
int MAX_T = -1;
auto dfs(int idx, int p = -1) -> void {
  auto nxt = to_val[a[idx]];
  ans[idx] = tr.get(1, nxt - 1) + 1;
  cerr << "idx val ans " << idx << ' ' << nxt << ' ' << ans[idx] << "\\n";
  tr.update(nxt, ans[idx]);
  vals[nxt].emplace_back(ans[idx]);

  for (auto &v : g[idx]) {
    if (v == p)
      continue;
    dfs(v, idx);
  }
  vals[nxt].pop_back();
  assert(!vals[nxt].empty());
  tr.update(nxt, vals[nxt].back());
}

auto dfs2(int idx, int p = -1) -> void {
  if (p != -1)
    ans[idx] = max(ans[idx], ans[p]);
  for (auto &v : g[idx]) {
    if (v == p)
      continue;
    dfs2(v, idx);
  }
}
auto main() -> int {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cin >> n;
  vector<int> tt;
  // memset(lazy, -1, sizeof lazy);
  for (int i = 1; i <= n; ++i) {
    cin >> a[i];
    tt.emplace_back(a[i]);
  }
  for (int i = 1; i < n; ++i) {
    int u, v;
    cin >> u >> v;
    g[u].emplace_back(v);
    g[v].emplace_back(u);
  }
  sort(tt.begin(), tt.end());
  tt.erase(unique(tt.begin(), tt.end()), tt.end());

  for (int i = 0; i < tt.size(); ++i) {
    to_val[tt[i]] = i + 1;
  }
  MAX_T = tt.size() + 6;
  // build(1, 1, MAX_T);
  tr = SegmentTreeMax(MAX_T - 1);
  for (int i = 1; i < MAX_T; ++i)
    vals[i].emplace_back(0);
  dfs(1);
  dfs2(1);
  for (int i = 1; i <= n; ++i)
    cout << ans[i] << '\\n';

  return 0;
}