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

#include <bits/stdc++.h>
// #include <boost/multiprecision/cpp_int.hpp>
using namespace std;

#define all(a) (a).begin(), (a).end()
#define rall(a) (a).rbegin(), (a).rend()
#define MIN(a) *std::min_element((a).begin(), (a).end())
#define MAX(a) *std::max_element((a).begin(), (a).end())
#define SUM(a) std::accumulate((a).begin(), (a).end(), 0LL)
#define REP(i, n) for (std::size_t(i) = 0; (i) < (n); (i)++)
#define RREP(i, n) for (std::size_t(i) = (n)-1; (i) >= 0; (i)--)
#define FOR(i, m, n) for (std::size_t(i) = (m); (i) < (n); i++)
#define FORR(i, m, n) for (std::size_t(i) = (n)-1; (i) >= (m); i--)
#define debug(x) std::cerr << #x << " = " << x << '\\n'
// #define int long long

using ll = long long;
using ull = unsigned long long;
using ld = long double;
using vl = std::vector<long long>;
using vvl = std::vector<std::vector<long long>>;
// using bint = boost::multiprecision::cpp_int;
// using rat = boost::rational<bint>;

constexpr int inf = (1 << 30) - 1;
constexpr long long INF = 1LL << 60;

inline void ios_() {
  std::cin.tie(nullptr);
  std::ios::sync_with_stdio(false);
}
template <typename T> inline T Div(const T &a, const T &b) {
  return (a + b - 1) / b;
}
template <typename T> bool chmin(T &a, const T &b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
template <typename T> bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}

template <typename T> inline void finish(const T &msg) {
  std::cout << msg << std::endl;
  std::exit(0);
}

template <typename T>
long long binarySearch(long long ng, long long ok, const T &fn) {
  while (std::abs(ok - ng) > 1) {
    T mid = (ok + ng) / 2;
    if (fn(mid))
      ok = mid;
    else
      ng = mid;
  }
  return ok;
}

struct ModInt {
  long long value;
  static const long long mod; // mod must be a prime number

  ModInt(long long v = 0) : value(((v % mod) + mod) % mod) {}

  ModInt pow(long long n) const {
    long long x = value, res = 1;
    while (n > 0) {
      if (n & 1) {
        res = res * x % mod;
      }
      x = x * x % mod;
      n >>= 1;
    }
    return ModInt(res);
  }

  ModInt inverse() const { return pow(mod - 2); }

  ModInt operator-() const { return ModInt((mod - value) % mod); }

  ModInt &operator+=(const ModInt &a) {
    value += a.value;
    value %= mod;
    return *this;
  }

  ModInt &operator-=(const ModInt &a) {
    value += (-a).value;
    value %= mod;
    return *this;
  }

  ModInt &operator*=(const ModInt &a) {
    value *= a.value;
    value %= mod;
    return *this;
  }

  ModInt &operator/=(const ModInt &a) { return (*this) *= a.inverse(); }

  ModInt operator+(const ModInt &a) const { return ModInt(*this) += a; }

  ModInt operator-(const ModInt &a) const { return ModInt(*this) -= a; }

  ModInt operator*(const ModInt &a) const { return ModInt(*this) *= a; }

  ModInt operator/(const ModInt &a) const { return ModInt(*this) /= a; }

  bool operator==(const ModInt &a) const { return value == a.value; }

  bool operator!=(const ModInt &a) const { return value != a.value; }

  friend std::istream &operator>>(std::istream &is, ModInt &a) {
    long long v;
    is >> v;
    a = v;
    return is;
  }

  friend std::ostream &operator<<(std::ostream &os, const ModInt &a) {
    os << a.value;
    return os;
  }

  static ModInt factorial(int n) {
    static std::vector<ModInt> fact(1 << 18);
    if (fact.size() <= n) {
      fact.resize(n + 1);
    }
    if (n < 0) {
      return 0;
    }
    if (n == 0) {
      return 1;
    }
    if (fact[n] != 0) {
      return fact[n];
    }
    return fact[n] = factorial(n - 1) * n;
  }

  static ModInt combin(int n, int k) {
    if (n < 0 || k < 0 || n < k) {
      return 0;
    }
    return factorial(n) / (factorial(k) * factorial(n - k));
  }
};
const long long ModInt::mod = 1e9 + 7;
// const long long ModInt::mod = 998244353;
using mint = ModInt;

signed main() {
  int n, k;
  cin >> n >> k;
  vector<int> v(n);
  for (auto &&i : v)
    cin >> i;

  chmin(k, 50);

  REP(hoge, k) {
    vector<int> sum(n + 1);
    REP(i, n) {
      int l = max(0, (int)i - v[i]);
      int r = min(n - 1, (int)i + v[i]);
      sum[l]++;
      sum[r + 1]--;
    }
    REP(i, n) { sum[i + 1] += sum[i]; }
    v = sum;
  }

  REP(i, n) { cout << v[i] << " "; }
  cout << endl;

  return 0;
}


Error: TLE

Fixed submission:

#include <bits/stdc++.h>
// #include <boost/multiprecision/cpp_int.hpp>
using namespace std;

#define all(a) (a).begin(), (a).end()
#define rall(a) (a).rbegin(), (a).rend()
#define MIN(a) *std::min_element((a).begin(), (a).end())
#define MAX(a) *std::max_element((a).begin(), (a).end())
#define SUM(a) std::accumulate((a).begin(), (a).end(), 0LL)
#define REP(i, n) for (std::size_t(i) = 0; (i) < (n); (i)++)
#define RREP(i, n) for (std::size_t(i) = (n)-1; (i) >= 0; (i)--)
#define FOR(i, m, n) for (std::size_t(i) = (m); (i) < (n); i++)
#define FORR(i, m, n) for (std::size_t(i) = (n)-1; (i) >= (m); i--)
#define debug(x) std::cerr << #x << " = " << x << '\\n'
// #define int long long

using ll = long long;
using ull = unsigned long long;
using ld = long double;
using vl = std::vector<long long>;
using vvl = std::vector<std::vector<long long>>;
// using bint = boost::multiprecision::cpp_int;
// using rat = boost::rational<bint>;

constexpr int inf = (1 << 30) - 1;
constexpr long long INF = 1LL << 60;

inline void ios_() {
  std::cin.tie(nullptr);
  std::ios::sync_with_stdio(false);
}
template <typename T> inline T Div(const T &a, const T &b) {
  return (a + b - 1) / b;
}
template <typename T> bool chmin(T &a, const T &b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
template <typename T> bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}

template <typename T> inline void finish(const T &msg) {
  std::cout << msg << std::endl;
  std::exit(0);
}

template <typename T>
long long binarySearch(long long ng, long long ok, const T &fn) {
  while (std::abs(ok - ng) > 1) {
    T mid = (ok + ng) / 2;
    if (fn(mid))
      ok = mid;
    else
      ng = mid;
  }
  return ok;
}

struct ModInt {
  long long value;
  static const long long mod; // mod must be a prime number

  ModInt(long long v = 0) : value(((v % mod) + mod) % mod) {}

  ModInt pow(long long n) const {
    long long x = value, res = 1;
    while (n > 0) {
      if (n & 1) {
        res = res * x % mod;
      }
      x = x * x % mod;
      n >>= 1;
    }
    return ModInt(res);
  }

  ModInt inverse() const { return pow(mod - 2); }

  ModInt operator-() const { return ModInt((mod - value) % mod); }

  ModInt &operator+=(const ModInt &a) {
    value += a.value;
    value %= mod;
    return *this;
  }

  ModInt &operator-=(const ModInt &a) {
    value += (-a).value;
    value %= mod;
    return *this;
  }

  ModInt &operator*=(const ModInt &a) {
    value *= a.value;
    value %= mod;
    return *this;
  }

  ModInt &operator/=(const ModInt &a) { return (*this) *= a.inverse(); }

  ModInt operator+(const ModInt &a) const { return ModInt(*this) += a; }

  ModInt operator-(const ModInt &a) const { return ModInt(*this) -= a; }

  ModInt operator*(const ModInt &a) const { return ModInt(*this) *= a; }

  ModInt operator/(const ModInt &a) const { return ModInt(*this) /= a; }

  bool operator==(const ModInt &a) const { return value == a.value; }

  bool operator!=(const ModInt &a) const { return value != a.value; }

  friend std::istream &operator>>(std::istream &is, ModInt &a) {
    long long v;
    is >> v;
    a = v;
    return is;
  }

  friend std::ostream &operator<<(std::ostream &os, const ModInt &a) {
    os << a.value;
    return os;
  }

  static ModInt factorial(int n) {
    static std::vector<ModInt> fact(1 << 18);
    if (fact.size() <= n) {
      fact.resize(n + 1);
    }
    if (n < 0) {
      return 0;
    }
    if (n == 0) {
      return 1;
    }
    if (fact[n] != 0) {
      return fact[n];
    }
    return fact[n] = factorial(n - 1) * n;
  }

  static ModInt combin(int n, int k) {
    if (n < 0 || k < 0 || n < k) {
      return 0;
    }
    return factorial(n) / (factorial(k) * factorial(n - k));
  }
};
const long long ModInt::mod = 1e9 + 7;
// const long long ModInt::mod = 998244353;
using mint = ModInt;

template <typename T> struct SegmentTree {
  int N;                // 要素数
  T idt;                // 単位元
  vector<T> node;       // ノード (1-indexed, node[0]=idt)
  function<T(T, T)> fn; // 二項演算

  // 要素を引数のベクトルから受け取る
  SegmentTree(const vector<T> &v, T id, function<T(T, T)> f) : idt(id), fn(f) {
    N = 1 << calcRank(v.size());
    node.resize(2 * N);

    for (int i = 0; i < 2 * N; i++) {
      if (i >= N && i < N + v.size()) { // 最下層のノードに要素を格納
        node[i] = v[i - N];
      } else {
        node[i] = idt;
      }
    }

    build();
  }

  int calcRank(int n) {
    int res = 0;
    n--;
    while (n > 0) {
      res++;
      n /= 2;
    }
    return res;
  }

  void build() {
    for (int i = N - 1; i > 0; i--) {
      node[i] = fn(node[2 * i], node[2 * i + 1]);
    }
  }

  void update(int k, T value) { // 値の更新
    k += N;                     // 要素番号->ノード番号
    node[k] = value;

    while (k > 1) {
      k /= 2;
      node[k] = fn(node[2 * k], node[2 * k + 1]); // 上に向かって値を更新する
    }
  }

  T query(int a, int b) { // 半開区間 [a,b) に対するクエリ
    return query(a, b, 1, 0, N);
  }

  T query(int a, int b, int k, int l, int r) { // 計算用の内部関数
    if (r <= a || b <= l) { //[a,b) と [l,r) が交差しない場合
      return idt;
    }
    if (a <= l && r <= b) { //[l,r) が [a,b) に含まれる場合
      return node[k];
    }

    T vl = query(a, b, 2 * k, l, (l + r) / 2); // 左右に分けて再帰
    T vr = query(a, b, 2 * k + 1, (l + r) / 2, r);

    return fn(vl, vr);
  }
};

template <typename T> struct LazySegmentTree : SegmentTree<T> {
  vector<T> lazy;
  function<T(T, T)> gn;
  function<T(T, int)> p;

  LazySegmentTree(const vector<T> &v, T id, function<T(T, T)> f,
                  function<T(T, T)> g, function<T(T, int)> p)
      : SegmentTree<T>(v, id, f), gn(g), p(p) {
    lazy.resize(2 * this->N, id);
  }

  void eval(int k, int len) { // 遅延配列のデータを適用
    if (lazy[k] == this->idt)
      return;
    if (k < this->N) {
      lazy[2 * k] = gn(lazy[2 * k], lazy[k]);
      lazy[2 * k + 1] = gn(lazy[2 * k + 1], lazy[k]);
    }
    this->node[k] = gn(this->node[k], p(lazy[k], len));
    lazy[k] = this->idt;
  }

  T update(int a, int b, T value, int k, int l, int r) {
    eval(k, r - l);

    if (r <= a || b <= l)
      return this->node[k];
    if (a <= l && r <= b) {
      lazy[k] = gn(lazy[k], value);
      return gn(this->node[k], p(lazy[k], r - l));
    }

    T vl = update(a, b, value, k * 2, l, (l + r) / 2);
    T vr = update(a, b, value, 2 * k + 1, (l + r) / 2, r);
    return this->node[k] = this->fn(vl, vr);
  }

  void update(int a, int b, T value) { // 区間 [a,b) を更新
    update(a, b, value, 1, 0, this->N);
  }

  T query(int a, int b, int k, int l, int r) {
    eval(k, r - l);

    if (r <= a || b <= l)
      return this->idt;
    if (a <= l && r <= b)
      return this->node[k];

    T vl = query(a, b, 2 * k, l, (l + r) / 2);
    T vr = query(a, b, 2 * k + 1, (l + r) / 2, r);

    return this->fn(vl, vr);
  }

  T query(int a, int b) { // 半開区間 [a,b) に対するクエリ
    return query(a, b, 1, 0, this->N);
  }
};

signed main() {
  int n, k;
  cin >> n >> k;
  vector<int> v(n);
  for (auto &&i : v)
    cin >> i;

  LazySegmentTree<int> tree(
      v, 0, [](int a, int b) { return a + b; },
      [](int a, int b) { return a + b; }, [](int a, int p) { return a * p; });

  LazySegmentTree<int> t2(tree);

  chmin(k, 50);

  REP(hoge, k) {
    t2 = LazySegmentTree<int>(
        vector<int>(n, 0), 0, [](int a, int b) { return a + b; },
        [](int a, int b) { return a + b; }, [](int a, int p) { return a * p; });
    REP(i, n) {
      int a = tree.query(i, i + 1);
      t2.update(max(0, (int)i - a), min(n, (int)(i + a + 1)), 1);
    }
    tree = t2;
  }

  REP(i, n) { cout << tree.query(i, i + 1) << " "; }
  cout << endl;

  return 0;
}