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

#include "bits/stdc++.h"
using namespace std;
typedef long long li;

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);

  string s;
  cin >> s;

  li min_maximum = 0, cur = 0;
  vector<li> min_offset(1, 0);
  for (int i = 0; i < s.size(); ++i) {
    if (s[i] == '1') {
      cur += 1;
    } else {
      cur -= 1;
    }
    min_offset.emplace_back(cur);
    min_maximum = max(cur, min_maximum);
  }
  vector<li> back_max(s.size() + 1, min_offset.back());
  for (int i = s.size() - 1; i >= 0; --i) {
    back_max[i] = max(back_max[i + 1], min_offset[i]);
  }

  li ans = s.size();
  for (int ub = min_maximum; ub < min_maximum + 2; ++ub) {
    li cur = 0, maximum = 0, minimum = 0;
    for (int i = 0; i < s.size(); ++i) {
      if (s[i] == '0') {
        cur -= 1;
      } else if (s[i] == '1') {
        cur += 1;
      } else {
        if (cur + 1 + max(0LL, back_max[i + 1] - min_offset[i + 1]) > ub) {
          cur -= 1;
        } else {
          cur += 1;
        }
      }
      maximum = max(maximum, cur);
      minimum = min(minimum, cur);
    }
    ans = min(ans, maximum - minimum);
  }

  cout << ans << endl;

  return 0;
}

Error: TLE

Fixed submission:

#include "bits/stdc++.h"
using namespace std;
typedef long long li;

typedef pair<li, li> numAndMin;

template <class T, class E> struct RangeUpdateLinearAmplifySegmentTree {
  T aggregation(T x, T y) {
    // y is right element
    return numAndMin(x.first + y.first, min(x.second, y.second));
  }

  T apply(E e, T t) {
    return numAndMin(t.first + e.first, min(t.second, t.first + e.second));
  }

  E merge(E x, E y) {
    // y is applied later
    return numAndMin(x.first + y.first, min(x.second, x.first + y.second));
  }

  E amplify(int x, E e) { return numAndMin(x * e.first, x * e.second); }

  T default_element() {
    // identity of aggregation
    return numAndMin(0, 0);
  }

  E default_operator() {
    // identity of merge
    return numAndMin(0, 0);
  }

  int offset;
  vector<T> buffer;
  vector<E> operator_buffer;

  RangeUpdateLinearAmplifySegmentTree(const vector<T> &initial_values) {
    const int n = initial_values.size();
    int row_length = 1;
    while (n > row_length) {
      row_length *= 2;
    }
    offset = row_length - 1;
    buffer = vector<T>(row_length * 2, default_element());
    operator_buffer = vector<E>(row_length * 2, default_operator());
    for (int i = 0; i < n; ++i) {
      buffer[offset + i] = initial_values[i];
    }
    initialize_buffer();
  }

  void initialize_buffer() {
    for (int i = offset - 1; i >= 0; --i) {
      buffer[i] = aggregation(buffer[2 * i + 1], buffer[2 * i + 2]);
    }
  }

  void propagate(int length, int i) {
    if (operator_buffer[i] == default_operator()) {
      return;
    }
    if (i * 2 + 2 < operator_buffer.size()) {
      operator_buffer[i * 2 + 1] =
          merge(operator_buffer[i * 2 + 1], operator_buffer[i]);
      operator_buffer[i * 2 + 2] =
          merge(operator_buffer[i * 2 + 2], operator_buffer[i]);
    }
    buffer[i] = apply(amplify(length, operator_buffer[i]), buffer[i]);
    operator_buffer[i] = default_operator();
  }

  // [l, r)
  T aggregate(int l, int r) {
    return aggregate_recursive(l, r, 0, 0, offset + 1);
  }

  T aggregate_recursive(int l, int r, int i, int p, int q) {
    propagate(q - p, i);
    if (q <= l || r <= p) {
      return default_element();
    }
    if (l <= p && q <= r) {
      return buffer[i];
    }
    const int left = 2 * i + 1;
    const int right = left + 1;
    const int m = (p + q) / 2;

    return aggregation(aggregate_recursive(l, r, left, p, m),
                       aggregate_recursive(l, r, right, m, q));
  }

  // for i in [l, r), buf[i] := E(buf[i])
  void update(int l, int r, E x) {
    update_recursive(l, r, x, 0, 0, offset + 1);
  }

  T update_recursive(int l, int r, E x, int i, int p, int q) {
    propagate(q - p, i);
    if (q <= l || r <= p) {
      return buffer[i];
    }
    if (l <= p && q <= r) {
      operator_buffer[i] = merge(operator_buffer[i], x);
      return apply(amplify(q - p, operator_buffer[i]), buffer[i]);
    }
    const int left = 2 * i + 1;
    const int right = left + 1;
    const int m = (p + q) / 2;

    return buffer[i] = aggregation(update_recursive(l, r, x, left, p, m),
                                   update_recursive(l, r, x, right, m, q));
  }

  T get_at(int i) { return aggregate(i, i + 1); }
};

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);

  string s;
  cin >> s;

  const li tree_size = (s.size() + 1) / 2 + 1;
  vector<numAndMin> even_init_values(tree_size), odd_init_values(tree_size);
  for (int i = 0; i < tree_size; ++i) {
    even_init_values[i] = make_pair(-i * 2, -i * 2);
    odd_init_values[i] = make_pair(-i * 2 - 1, -i * 2 - 1);
  }
  RangeUpdateLinearAmplifySegmentTree<numAndMin, numAndMin> even_tree(
      even_init_values),
      odd_tree(odd_init_values);

  li min_maximum = 0, cur = 0;
  vector<li> min_offset(1, 0);
  for (int i = 0; i < s.size(); ++i) {
    if (s[i] == '1') {
      cur += 1;
    } else {
      cur -= 1;
    }
    min_offset.emplace_back(cur);
    min_maximum = max(cur, min_maximum);
  }
  vector<li> back_max(s.size() + 1, min_offset.back());
  for (int i = s.size() - 1; i >= 0; --i) {
    back_max[i] = max(back_max[i + 1], min_offset[i]);
  }

  const li even_min_index = (min_maximum + 1) / 2;
  const li odd_min_index = min_maximum / 2;

  for (int i = 0; i < s.size(); ++i) {
    if (s[i] == '0') {
      even_tree.update(even_min_index, tree_size, make_pair(-1, -1));
      odd_tree.update(odd_min_index, tree_size, make_pair(-1, -1));
    } else if (s[i] == '1') {
      even_tree.update(even_min_index, tree_size, make_pair(1, 1));
      odd_tree.update(odd_min_index, tree_size, make_pair(1, 1));
    } else {
      {
        li p = even_min_index - 1, q = tree_size;
        while (q - p > 1) {
          li m = (p + q) / 2;
          if (even_tree.get_at(m).first + 1 +
                  max(0LL, back_max[i + 1] - min_offset[i + 1]) >
              0) {
            p = m;
          } else {
            q = m;
          }
        }
        even_tree.update(even_min_index, q, make_pair(-1, -1));
        even_tree.update(q, tree_size, make_pair(1, 1));
      }
      {
        li p = odd_min_index - 1, q = tree_size;
        while (q - p > 1) {
          li m = (p + q) / 2;
          if (odd_tree.get_at(m).first + 1 +
                  max(0LL, back_max[i + 1] - min_offset[i + 1]) >
              0) {
            p = m;
          } else {
            q = m;
          }
        }
        odd_tree.update(odd_min_index, q, make_pair(-1, -1));
        odd_tree.update(q, tree_size, make_pair(1, 1));
      }
    }
  }

  li ans = s.size();
  for (int i = 0; i < tree_size; ++i) {
    if (i >= even_min_index) {
      ans = min(ans, -even_tree.get_at(i).second);
    }
    if (i >= odd_min_index) {
      ans = min(ans, -odd_tree.get_at(i).second);
    }
  }
  cout << ans << endl;

  return 0;
}