#include "towers.h"
#include <cassert>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <functional>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
using namespace std;
using Int = long long;
template <class T1, class T2> ostream &operator<<(ostream &os, const pair<T1, T2> &a) { return os << "(" << a.first << ", " << a.second << ")"; };
template <class T> ostream &operator<<(ostream &os, const vector<T> &as) { const int sz = as.size(); os << "["; for (int i = 0; i < sz; ++i) { if (i >= 256) { os << ", ..."; break; } if (i > 0) { os << ", "; } os << as[i]; } return os << "]"; }
template <class T> void pv(T a, T b) { for (T i = a; i != b; ++i) cerr << *i << " "; cerr << endl; }
template <class T> bool chmin(T &t, const T &f) { if (t > f) { t = f; return true; } return false; }
template <class T> bool chmax(T &t, const T &f) { if (t < f) { t = f; return true; } return false; }
#define COLOR(s) ("\x1b[" s "m")
struct Set {
// max{ceil(log_64(n)), 1}
int log64N, n;
vector<unsigned long long> a[6];
explicit Set(int n_ = 0) : n(n_) {
assert(n >= 0);
int m = n ? n : 1;
for (int d = 0; ; ++d) {
m = (m + 63) >> 6;
a[d].assign(m, 0);
if (m == 1) {
log64N = d + 1;
break;
}
}
}
bool empty() const {
return !a[log64N - 1][0];
}
bool contains(int x) const {
return (a[0][x >> 6] >> (x & 63)) & 1;
}
void insert(int x) {
for (int d = 0; d < log64N; ++d) {
const int q = x >> 6, r = x & 63;
a[d][q] |= 1ULL << r;
x = q;
}
}
void erase(int x) {
for (int d = 0; d < log64N; ++d) {
const int q = x >> 6, r = x & 63;
if ((a[d][q] &= ~(1ULL << r))) break;
x = q;
}
}
// max s.t. <= x (or -1)
int prev(int x) const {
if (x > n - 1) x = n - 1;
for (int d = 0; d <= log64N; ++d) {
if (x < 0) break;
const int q = x >> 6, r = x & 63;
const unsigned long long lower = a[d][q] << (63 - r);
if (lower) {
x -= __builtin_clzll(lower);
for (int e = d; --e >= 0; ) x = x << 6 | (63 - __builtin_clzll(a[e][x]));
return x;
}
x = q - 1;
}
return -1;
}
// min s.t. >= x (or n)
int next(int x) const {
if (x < 0) x = 0;
for (int d = 0; d < log64N; ++d) {
const int q = x >> 6, r = x & 63;
if (static_cast<unsigned>(q) >= a[d].size()) break;
const unsigned long long upper = a[d][q] >> r;
if (upper) {
x += __builtin_ctzll(upper);
for (int e = d; --e >= 0; ) x = x << 6 | __builtin_ctzll(a[e][x]);
return x;
}
x = q + 1;
}
return n;
}
};
////////////////////////////////////////////////////////////////////////////////
constexpr int INF = 1001001001;
vector<pair<int, int>> anss;
void init(int N, std::vector<int> H) {
vector<int> is;
for (int i = 0, j, k; i < N - 1; i = k) {
for (j = i; j < N - 1 && H[j] < H[j + 1]; ++j) {}
for (k = j; k < N - 1 && H[k] > H[k + 1]; ++k) {}
if (i < j && j < k) {
if (is.size()) {
assert(is.back() == i);
is.pop_back();
}
is.push_back(i);
is.push_back(j);
is.push_back(k);
}
}
int now = (int)is.size() / 2;
Set on(N);
using Entry = pair<int, pair<int, int>>;
priority_queue<Entry, vector<Entry>, greater<Entry>> que;
for (const int i : is) {
on.insert(i);
}
for (int j = 0; j < 2 * now; ++j) {
que.emplace(abs(H[is[j]] - H[is[j + 1]]), make_pair(is[j], is[j + 1]));
}
for (; que.size(); ) {
const int d = que.top().first;
const int i = que.top().second.first;
const int j = que.top().second.second;
que.pop();
if (on.contains(i) && on.contains(j)) {
// cerr<<"d = "<<d<<", i = "<<i<<", j = "<<j<<"; on = ";for(int k=0;k<N;++k)if(on.contains(k))cerr<<make_pair(H[k],k)<<" ";cerr<<endl;
anss.emplace_back(d, -now);
now -= 2;
on.erase(i);
on.erase(j);
const int l = on.prev(i);
const int r = on.next(j);
if (0 <= l && r < N) {
que.emplace(abs(H[l] - H[r]), make_pair(l, r));
}
}
}
anss.emplace_back(INF, -1);
// cerr<<"anss = "<<anss<<endl;
}
int max_towers(int L, int R, int D) {
++R;
assert(L == 0);
assert(R == N);
return -lower_bound(anss.begin(), anss.end(), make_pair(D, -INF))->second + 1;
}