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

#include <algorithm>
#include <bitset>
#include <cmath>
#include <cstdint>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>

#define N_TIMES(i, n) for (uint64_t i = 0; i < n; ++i)
#define N_TIMES_REV(i, n) for (int64_t i = n - 1; i >= 0; --i)

template <typename T>
using maximum_heap = std::priority_queue<T, std::vector<T>, std::less<T>>;
template <typename T>
using minimum_heap = std::priority_queue<T, std::vector<T>, std::greater<T>>;

template <typename T>
std::istream &operator>>(std::istream &is, std::vector<T> &v) {
  for (typename std::vector<T>::size_type i = 0; i < v.size(); ++i) {
    is >> v[i];
  }
  return is;
}

using namespace std;

const uint64_t M = 41;

int main() {
  uint64_t N, K;
  cin >> N >> K;

  vector<uint64_t> A(N);
  cin >> A;

  auto simulate = [&](const vector<uint64_t> &a) {
    vector<int64_t> b(N + 1, 0);
    N_TIMES(n, N) {
      pair<int64_t, int64_t> range(static_cast<int64_t>(n) - a[n],
                                   static_cast<int64_t>(n) + a[n]);
      range.first = max(range.first, static_cast<int64_t>(0));
      range.second = min(range.second, static_cast<int64_t>(N - 1));

      ++b[range.first];
      --b[range.second + 1];
    }

    uint64_t t = 0;
    vector<uint64_t> c(N, 0);
    N_TIMES(n, N) {
      t += b[n];
      c[n] = t;
    }
    return c;
  };

  vector<uint64_t> B = A;
  N_TIMES(k, min(K, M)) { B = simulate(B); }

  N_TIMES(n, N) {
    cout << B[n];
    if (n + 1 < N) {
      cout << ' ';
    }
  }
  cout << endl;

  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <bitset>
#include <cmath>
#include <cstdint>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>

#define N_TIMES(i, n) for (uint64_t i = 0; i < n; ++i)
#define N_TIMES_REV(i, n) for (int64_t i = n - 1; i >= 0; --i)

template <typename T>
using maximum_heap = std::priority_queue<T, std::vector<T>, std::less<T>>;
template <typename T>
using minimum_heap = std::priority_queue<T, std::vector<T>, std::greater<T>>;

template <typename T>
std::istream &operator>>(std::istream &is, std::vector<T> &v) {
  for (typename std::vector<T>::size_type i = 0; i < v.size(); ++i) {
    is >> v[i];
  }
  return is;
}

template <typename INDEX_TYPE, typename VALUE_TYPE, VALUE_TYPE Undefined,
          class Add = std::plus<VALUE_TYPE>>
class RangeAddQueryBase {
private:
  std::vector<VALUE_TYPE> segment_tree;
  INDEX_TYPE N, M;

  INDEX_TYPE _upper_bound_by_power_of_2(INDEX_TYPE n) const {
    return 1 << static_cast<INDEX_TYPE>(
               ::ceill(::log2l(static_cast<long double>(n))));
  }

  VALUE_TYPE _build_segment_tree(const std::vector<VALUE_TYPE> &a,
                                 INDEX_TYPE i = 0) {
    if (i >= (M << 1)) {
      return Undefined;
    }

    segment_tree[i] = Undefined;

    _build_segment_tree(a, 2 * i + 1);
    _build_segment_tree(a, 2 * i + 2);

    return segment_tree[i];
  }

  void _lazy_update(INDEX_TYPE i) {
    if (segment_tree[i] != Undefined && i < M - 1) {
      segment_tree[2 * i + 1] = Add()(segment_tree[2 * i + 1], segment_tree[i]);
      segment_tree[2 * i + 2] = Add()(segment_tree[2 * i + 2], segment_tree[i]);
      segment_tree[i] = Undefined;
    }
  }

  bool _add(INDEX_TYPE left, INDEX_TYPE right, VALUE_TYPE value, INDEX_TYPE lb,
            INDEX_TYPE ub, INDEX_TYPE i) {
    _lazy_update(i);

    if (ub <= left || right <= lb) {
      return false;
    }

    if (left <= lb && ub <= right) {
      segment_tree[i] = Add()(segment_tree[i], value);
      _lazy_update(i);
      return true;
    }

    INDEX_TYPE mid = (lb + ub) / 2;
    bool f = _add(left, right, value, lb, mid, 2 * i + 1);
    bool g = _add(left, right, value, mid, ub, 2 * i + 2);
    return f || g;
  }

  VALUE_TYPE _get(INDEX_TYPE index, INDEX_TYPE lb, INDEX_TYPE ub,
                  INDEX_TYPE i) {
    _lazy_update(i);

    if (ub - lb <= 1) {
      return segment_tree[i];
    }

    INDEX_TYPE mid = (lb + ub) / 2;
    if (index < mid) {
      return _get(index, lb, mid, 2 * i + 1);
    } else {
      return _get(index, mid, ub, 2 * i + 2);
    }
  }

public:
  RangeAddQueryBase(const std::vector<VALUE_TYPE> &a) {
    N = a.size();
    M = _upper_bound_by_power_of_2(N);

    segment_tree = std::vector<VALUE_TYPE>(M << 1, Undefined);

    for (INDEX_TYPE n = 0; n < N; ++n) {
      segment_tree[n + (M - 1)] = a[n];
    }

    _build_segment_tree(a);
  }

  bool add(INDEX_TYPE left, INDEX_TYPE right, VALUE_TYPE value) {
    return _add(left, right, value, 0, M, 0);
  }

  VALUE_TYPE get(INDEX_TYPE index) { return _get(index, 0, M, 0); }
};

const uint64_t Undefined = 0;

typedef RangeAddQueryBase<uint64_t, uint64_t, Undefined> RangeAddQuery;

using namespace std;

const uint64_t M = 41;

int main() {
  uint64_t N, K;
  cin >> N >> K;

  vector<uint64_t> A(N);
  cin >> A;

  auto simulate = [&](const vector<uint64_t> &a) {
    RangeAddQuery raq(vector<uint64_t>(N, 0));
    N_TIMES(n, N) {
      pair<int64_t, int64_t> range(static_cast<int64_t>(n) - a[n],
                                   static_cast<int64_t>(n) + a[n]);
      range.first = max(range.first, static_cast<int64_t>(0));
      range.second = min(range.second, static_cast<int64_t>(N - 1));
      raq.add(range.first, range.second + 1, +1);
    }

    vector<uint64_t> b(N, 0);
    N_TIMES(n, N) { b[n] = raq.get(n); }
    return b;
  };

  vector<uint64_t> B = A;
  N_TIMES(k, min(K, M)) { B = simulate(B); }

  N_TIMES(n, N) {
    cout << B[n];
    if (n + 1 < N) {
      cout << ' ';
    }
  }
  cout << endl;

  return 0;
}