#include "towers.h"
#include <bits/stdc++.h>
using namespace std;
struct node{
  int L, R, C;
  node *left, *right;
  void init(){
    if(L < R){
      left = new node({L, (L+R)/2, 0, NULL, NULL});
      right = new node({(L+R)/2+1, R, 0, NULL, NULL});
      left->init();
      right->init();
    }
  }
  void update(int K, node *M){
    C++;
    if(L == R)return;
    if(K > (L+R)/2){
      left = M->left;
      right = new node({(L+R)/2+1, R, M->right->C, NULL, NULL});
      right->update(K, M->right);
    }
    else{
      right = M->right;
      left = new node({L, (L+R)/2, M->left->C, NULL, NULL});
      left->update(K, M->left);
    }
  }
  int count(int x, int y){
    if(L > y || R < x)return 0;
    if(x <= L && y >= R)return C;
    return left->count(x, y) + right->count(x, y);
  }
  int left_index(int N){
    if(N > R)return 0;
    if(L == R)return C?R:0;
    if(!C)return 0;
    int t = left->left_index(N);
    return t?t:right->left_index(N);
  }
  int right_index(int N){
    if(N < L)return 0;
    if(L == R)return C?R:0;
    if(!C)return 0;
    int t = right->right_index(N);
    return t?t:left->right_index(N);
  }
};
struct segment_tree{
  int n, m;
  int H[100001], A[300000], B[300000], C[300000], D[300000];
  node *T[100001];
  queue<int> q;
  vector<pair<int, int>> E;
  void init(int N, vector<int> M){
    n = N;
    for(int i = 0; i < N; i++){
      H[i+1] = M[i];
      q.push(M[i]);
    }
    init_tree(1, 1, N);
    for(int i = 1; i <= N; i++){
      if((i > 1 && H[i-1] < H[i]) || (i < N && H[i] > H[i+1]))continue;
      int K = 1e9;
      if(i > 1 && min_value(1, 1, i-1, 1, N) <= H[i])K = min(K, max_value(1, get_right(1, i-1, H[i], 1, N)+1, i-1, 1, N)-H[i]);
      if(i < N && min_value(1, i+1, N, 1, N) <= H[i])K = min(K, max_value(1, i+1, get_left(1, i+1, H[i], 1, N)-1, 1, N)-H[i]);
      E.push_back(make_pair(-K, i));
    }
    sort(E.begin(), E.end());
    for(int i = 0; i < E.size(); i++)E[i].first = -E[i].first;
    T[0] = new node({1, N, 0, NULL, NULL});
    T[0]->init();
    for(int i = 1; i <= E.size(); i++){
      T[i] = new node({1, N, i-1, NULL, NULL});
      T[i]->update(E[i-1].second, T[i-1]);
    }
  }
  void init_tree(int N, int l, int r){
    if(l == r){
      A[N] = q.front();
      B[N] = q.front();
      q.pop();
      return;
    }
    init_tree(2*N, l, (l+r)/2);
    init_tree(2*N+1, (l+r)/2+1, r);
    A[N] = min(A[2*N], A[2*N+1]);
    B[N] = max(B[2*N], B[2*N+1]);
    C[N] = max(B[2*N+1]-A[2*N], max(C[2*N], C[2*N+1]));
    D[N] = max(B[2*N]-A[2*N+1], max(D[2*N], D[2*N+1]));
  }
  int min_value(int N, int x, int y, int l, int r){
    if(x > r || y < l)return 1000000001;
    if(x <= l && y >= r)return A[N];
    return min(min_value(2*N, x, y, l, (l+r)/2), min_value(2*N+1, x, y, (l+r)/2+1, r));
  }
  int max_value(int N, int x, int y, int l, int r){
    if(x > r || y < l)return 0;
    if(x <= l && y >= r)return B[N];
    return max(max_value(2*N, x, y, l, (l+r)/2), max_value(2*N+1, x, y, (l+r)/2+1, r));
  }
  int find_left(int N, int M, int K, int l, int r){
    if(M > r)return 0;
    if(l == r)return B[N]<K?0:r;
    if(B[N] < K)return 0;
    int t = find_left(2*N, M, K, l, (l+r)/2);
    return t?t:find_left(2*N+1, M, K, (l+r)/2+1, r);
  }
  int find_right(int N, int M, int K, int l, int r){
    if(M < l)return 0;
    if(l == r)return B[N]<K?0:r;
    if(B[N] < K)return 0;
    int t = find_right(2*N+1, M, K, (l+r)/2+1, r);
    return t?t:find_right(2*N, M, K, l, (l+r)/2);
  }
  int get_left(int N, int M, int K, int l, int r){
    if(M > r)return 0;
    if(l == r)return A[N]>K?0:r;
    if(A[N] > K)return 0;
    int t = get_left(2*N, M, K, l, (l+r)/2);
    return t?t:get_left(2*N+1, M, K, (l+r)/2+1, r);
  }
  int get_right(int N, int M, int K, int l, int r){
    if(M < l)return 0;
    if(l == r)return A[N]>K?0:r;
    if(A[N] > K)return 0;
    int t = get_right(2*N+1, M, K, (l+r)/2+1, r);
    return t?t:get_right(2*N, M, K, l, (l+r)/2);
  }
  int left_difference(int N, int x, int y, int *X, int *Y, int l, int r){
    if(x > r || y < l)return 0;
    if(x <= l && y >= r){
      *X = min(*X, A[N]);
      *Y = max(*Y, B[N]);
      return C[N];
    }
    int a = 1e9, b = 0;
    int L = left_difference(2*N, x, y, &a, Y, l, (l+r)/2);
    int R = left_difference(2*N+1, x, y, X, &b, (l+r)/2+1, r);
    *X = min(*X, a);
    *Y = max(*Y, b);
    return max(b-a, max(L, R));
  }
  int right_difference(int N, int x, int y, int *X, int *Y, int l, int r){
    if(x > r || y < l)return 0;
    if(x <= l && y >= r){
      *X = max(*X, B[N]);
      *Y = min(*Y, A[N]);
      return D[N];
    }
    int a = 0, b = 1e9;
    int L = right_difference(2*N, x, y, &a, Y, l, (l+r)/2);
    int R = right_difference(2*N+1, x, y, X, &b, (l+r)/2+1, r);
    *X = max(*X, a);
    *Y = min(*Y, b);
    return max(a-b, max(L, R));
  }
  int left_value(int N, int M, int K, int *Z, int l, int r){
    if(M > r)return 0;
    if(l == r){
      if(B[N]-*Z>=K)return r;
      *Z = min(*Z, A[N]);
      return 0;
    }
    if(B[N]-*Z<K)return 0;
    int L = left_value(2*N, M, K, Z, l, (l+r)/2);
    if(L)return L;
    int R = left_value(2*N+1, M, K, Z, (l+r)/2+1, r);
    *Z = min(*Z, A[N]);
    return R;
  }
  int right_value(int N, int M, int K, int *Z, int l, int r){
    if(M < l)return 0;
    if(l == r){
      if(B[N]-*Z>=K)return r;
      *Z = min(*Z, A[N]);
      return 0;
    }
    if(B[N]-*Z<K)return 0;
    int a = 0, b = 1e9;
    int R = right_value(2*N+1, M, K, Z, (l+r)/2+1, r);
    if(R)return R;
    int L = right_value(2*N, M, K, Z, l, (l+r)/2);
    *Z = min(*Z, A[N]);
    return L;
  }
  int state(int N){
    int L = 0, R = E.size()-1;
    while(L < R){
      int c = (L+R+1)/2;
      if(E[c].first < N)R = (L+R)/2;
      else L = c;
    }
    return R+1;
  }
} T;
void init(int N, vector<int> H) {
  T.init(N, H);
}
int max_towers(int L, int R, int D) {
  node* E = T.T[T.state(D)];
  int t = E->count(L+1, R+1);
  if(!t){
    if(T.left_difference(1, L+1, R+1, new int(1e9), new int(0), 1, T.n) < D || T.right_difference(1, L+1, R+1, new int(0), new int(1e9), 1, T.n) < D)return 1;
    if(T.left_value(1, L+1, D, new int(1000000001), 1, T.n) > T.right_value(1, R+1,D, new int(1000000001), 1, T.n))return 1;
    return 2;
  }
  int X = E->left_index(L+1);
  int Y = E->right_index(R+1);
  if(X > L+1 && T.max_value(1, L+1, X-1, 1, T.n) >= T.H[X]+D && T.left_difference(1, L+1, T.find_right(1, X, T.H[X]+D, 1, T.n), new int(1e9), new int(0), 1, T.n) >= D)t++;
  if(Y < R+1 && T.max_value(1, Y+1, R+1, 1, T.n) >= T.H[Y]+D && T.right_difference(1, T.find_left(1, Y, T.H[Y]+D, 1, T.n), R+1, new int(0), new int(1e9), 1, T.n) >= D)t++;
  return t;
}
| # | 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... |