This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include <bits/stdc++.h>
using namespace std;
#ifdef LOCAL
  #include "lib/debug.h"
#else
  #include "towers.h"
  #define debug(...) 0
#endif
typedef vector<int> vi;
const int N = 1e5, INF = 1e9 + 1;
template<typename Tp, int N>
struct Rmq_mn {
  static const int L = __lg(N - 1) + 1;
  Tp ar[1 << L], t[L][1 << L];
  Tp op(Tp l, Tp r) {
    return min(l, r);
  }
  void bld(int n, Tp *ar_) {
    int h = n == 1 ? 0 : __lg(n - 1) + 1;
    for (int i = 0; i < 1 << h; i++)
      ar[i] = i < n ? ar_[i] : Tp();
    bld(0, (1 << h) - 1, h - 1);
  }
  void bld(int l, int r, int h) {
    if (h >= 0) {
      int m = (l + r) / 2;
      for (int i = m; i >= l; i--)
        t[h][i] = i == m ? ar[i] : op(ar[i], t[h][i + 1]);
      for (int i = m + 1; i <= r; i++)
        t[h][i] = i == m + 1 ? ar[i] : op(t[h][i - 1], ar[i]);
      bld(l, m, h - 1), bld(m + 1, r, h - 1);
    }
  }
  Tp qry(int l, int r) {
    if (l > r)
      return INT_MAX;
    if (l == r)
      return ar[l];
    int h = __lg(l ^ r);
    return op(t[h][l], t[h][r]);
  }
};
template<typename Tp, int N>
struct Rmq_mx {
  static const int L = __lg(N - 1) + 1;
  Tp ar[1 << L], t[L][1 << L];
  int n;
  Tp op(Tp l, Tp r) {
    return max(l, r);
  }
  void bld(int n_, Tp *ar_) {
    n = n_;
    int h = n == 1 ? 0 : __lg(n - 1) + 1;
    for (int i = 0; i < 1 << h; i++)
      ar[i] = i < n ? ar_[i] : Tp();
    bld(0, (1 << h) - 1, h - 1);
  }
  void bld(int l, int r, int h) {
    if (h >= 0) {
      int m = (l + r) / 2;
      for (int i = m; i >= l; i--)
        t[h][i] = i == m ? ar[i] : op(ar[i], t[h][i + 1]);
      for (int i = m + 1; i <= r; i++)
        t[h][i] = i == m + 1 ? ar[i] : op(t[h][i - 1], ar[i]);
      bld(l, m, h - 1), bld(m + 1, r, h - 1);
    }
  }
  Tp qry(int l, int r) {
    l = max(l, 0);
    r = min(r, n - 1);
    if (l > r)
      return INT_MIN;
    if (l == r)
      return ar[l];
    int h = __lg(l ^ r);
    return op(t[h][l], t[h][r]);
  }
};
int n, u[N], v[N], v1[N + 1];
vi h;
Rmq_mx<int, N> rmq;
namespace s1 {
  const int N_ = N * 18;
  int s[N_], lc[N_], rc[N_], cnt = 0;
  int cp(int k) {
    int q = ++cnt;
    s[q] = s[k], lc[q] = lc[k], rc[q] = rc[k];
    return q;
  }
  void upd(int& k, int l, int r, int i) {
    k = cp(k);
    s[k]++;
    if (l != r) {
      int m = (l + r) / 2;
      if (i <= m)
        upd(lc[k], l, m, i);
      else
        upd(rc[k], m + 1, r, i);
    }
  }
  int sm(int k, int l, int r, int ql, int qr) {
    if (k == 0 || s[k] == 0 || ql > r || qr < l)
      return 0;
    if (ql <= l && qr >= r)
      return s[k];
    int m = (l + r) / 2;
    return sm(lc[k], l, m, ql, qr) + sm(rc[k], m + 1, r, ql, qr);
  }
  int gl(int k, int l, int r, int i) {
    if (l > i || s[k] == 0)
      return -1;
    if (l == r)
      return l;
    int m = (l + r) / 2, p = gl(rc[k], m + 1, r, i);
    return p != -1 ? p : gl(lc[k], l, m, i);
  }
  int gr(int k, int l, int r, int i) {
    if (r < i || s[k] == 0)
      return -1;
    if (l == r)
      return l;
    int m = (l + r) / 2, p = gr(lc[k], l, m, i);
    return p != -1 ? p : gr(rc[k], m + 1, r, i);
  }
  void print(int k, int l, int r) {
    if (k == 0)
      return;
    if (l == r) {
      cout << l << ' ';
      return;
    }
    int m = (l + r) / 2;
    print(lc[k], l, m), print(rc[k], m + 1, r);
  }
};
namespace s2 {
  struct V {
    int a, b, c;
  } s[N * 4], T = {INF, 0, 0};
  V op(V l, V r) {
    return {min(l.a, r.a), max(l.b, r.b), max(r.b - l.a, max(l.c, r.c))};
  }
  void bld() {
    for (int i = 0; i < n; i++)
      s[n + i] = {h[i], h[i], 0};
    for (int i = n - 1; i > 0; i--)
      s[i] = op(s[i * 2], s[i * 2 + 1]);
  }
  int qry(int l, int r) {
    V la = T, ra = T;
    for (l += n, r += n; l <= r; l /= 2, r /= 2) {
      if (l % 2 == 1)
        la = op(la, s[l++]);
      if (r % 2 == 0)
        ra = op(s[r--], ra);
    }
    return op(la, ra).c;
  }
  int val(int l, int r) {
    int x = INF;
    for (l += n, r += n; l <= r; l /= 2, r /= 2) {
      if (l % 2 == 1)
        x = min(x, s[l++].a);
      if (r % 2 == 0)
        x = min(x, s[r--].a);
    }
    return x;
  }
};
namespace s3 {
  struct V {
    int a, b, c;
  } s[N * 4], T = {INF, 0, 0};
  V op(V l, V r) {
    return {min(l.a, r.a), max(l.b, r.b), max(l.b - r.a, max(l.c, r.c))};
  }
  void bld() {
    for (int i = 0; i < n; i++)
      s[n + i] = {h[i], h[i], 0};
    for (int i = n - 1; i > 0; i--)
      s[i] = op(s[i * 2], s[i * 2 + 1]);
  }
  int qry(int l, int r) {
    V la = T, ra = T;
    for (l += n, r += n; l <= r; l /= 2, r /= 2) {
      if (l % 2 == 1)
        la = op(la, s[l++]);
      if (r % 2 == 0)
        ra = op(s[r--], ra);
    }
    return op(la, ra).c;
  }
  int val(int l, int r) {
    int x = INF;
    for (l += n, r += n; l <= r; l /= 2, r /= 2) {
      if (l % 2 == 1)
        x = min(x, s[l++].a);
      if (r % 2 == 0)
        x = min(x, s[r--].a);
    }
    return x;
  }
};
void init(int n_, vi h_) {
  n = n_;
  h = h_;
  rmq.bld(n, h.data());
  vi s;
  fill(v, v + n, INF);
  for (int i = 0; i < n; i++) {
    while (!s.empty() && h[s.back()] >= h[i])
      s.pop_back();
    if (!s.empty())
      v[i] = min(v[i], rmq.qry(s.back(), i) - h[i]);
    s.push_back(i);
  }
  s.clear();
  for (int i = n - 1; i >= 0; i--) {
    while (!s.empty() && h[s.back()] >= h[i])
      s.pop_back();
    if (!s.empty())
      v[i] = min(v[i], rmq.qry(i, s.back()) - h[i]);
    s.push_back(i);
  }
  s.clear();
  iota(u, u + n, 0);
  sort(u, u + n, [&](int i, int j) {
    return v[i] > v[j];
  });
  v1[0] = 0;
  for (int i = 0; i < n; i++) {
    v1[i + 1] = v1[i];
    s1::upd(v1[i + 1], 0, n - 1, u[i]);
  }
  s2::bld();
  s3::bld();
}
int Gl(int i, int d) {
  if (rmq.qry(1, i) < h[i] + d)
    return -1;
  int low = 0, hi = i - 1;
  while (low < hi) {
    int t = (low + hi) / 2 + 1;
    if (rmq.qry(t + 1, i) >= h[i] + d)
      low = t;
    else
      hi = t - 1;
  }
  return low;
}
int Gr(int i, int d) {
  if (rmq.qry(i, n - 2) < h[i] + d)
    return n;
  int low = i + 1, hi = n - 1;
  while (low < hi) {
    int t = (low + hi) / 2;
    if (rmq.qry(i, t - 1) >= h[i] + d)
      hi = t;
    else
      low = t + 1;
  }
  return low;
}
int max_towers(int l, int r, int d) {
  int low = 1, hi = n;
  while (low < hi) {
    int t = (low + hi) / 2 + 1;
    if (v[u[t - 1]] >= d)
      low = t;
    else
      hi = t - 1;
  }
  int x = s1::sm(v1[low], 0, n - 1, l, r);
  int L = s1::gr(v1[low], 0, n - 1, l);
  if (L != -1) {
    int l_ = Gl(L, d);
    if (s2::qry(l, l_) >= d || (l <= l_ && rmq.qry(max(l, l_), L) - s2::val(l, l_) >= d)) {
      x++;
      debug(L, l_);
    }
  }
  int R = s1::gl(v1[low], 0, n - 1, r);
  if (R != -1) {
    int r_ = Gr(R, d);
    if (s3::qry(r_, r) >= d || (r_ <= r && rmq.qry(R, min(r, r_)) - s3::val(r_, r) >= d)) {
      x++;
      debug(R, r_);
    }
  }
  return max(1, x);
}
Compilation message (stderr)
towers.cpp: In function 'int max_towers(int, int, int)':
towers.cpp:8:22: warning: statement has no effect [-Wunused-value]
    8 |   #define debug(...) 0
      |                      ^
towers.cpp:293:7: note: in expansion of macro 'debug'
  293 |       debug(L, l_);
      |       ^~~~~
towers.cpp:8:22: warning: statement has no effect [-Wunused-value]
    8 |   #define debug(...) 0
      |                      ^
towers.cpp:301:7: note: in expansion of macro 'debug'
  301 |       debug(R, r_);
      |       ^~~~~| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... |