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

#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <vector>
using namespace std;

#define REP2(i, m, n) for (int i = (int)(m); i < (int)(n); i++)
#define REP(i, n) REP2(i, 0, n)
#define ALL(c) (c).begin(), (c).end()
#define FOREACH(i, c) for (auto i = (c).begin(); i != (c).end(); ++i)
#define BIT(n, m) (((n) >> (m)) & 1)

typedef long long ll;
typedef pair<int, int> PI;

const ll inf = 1e15;
const ll mod = 1000 * 1000 * 1000 + 7;
const double eps = 1e-9;

template <typename S, typename T>
ostream &operator<<(ostream &out, const pair<S, T> &p) {
  out << "(" << p.first << ", " << p.second << ")";
  return out;
}

template <typename T> ostream &operator<<(ostream &out, const vector<T> &v) {
  out << "[";
  REP(i, v.size()) {
    if (i > 0)
      out << ", ";
    out << v[i];
  }
  out << "]";
  return out;
}

bool check(const vector<int> &V, ll W, ll L) {
  vector<ll> sum1(V.size() + 1);
  vector<ll> sumL(V.size() + 1);
  REP(i, V.size()) {
    sum1[i + 1] = sum1[i] + V[i] + 1;
    sumL[i + 1] = sumL[i] + V[i] + L;
  }

  vector<int> dp(V.size() + 1); // dp[i] = V[0..i)???valid?????????
  dp[0] = 0;
  dp[1] = 1;
  dp[2] = 1;

  REP2(i, 2, V.size()) {
    // int llb = -1;
    // int lub =
    // find max x s.t. sum of V[i - x, i) + (x - 1) <= W
    int left = i - 2;
    int right = i - 1;
    {
      int lb = -1;
      int &ub = left;
      while (ub - lb > 1) {
        int mb = (ub + lb) >> 1;
        ll sum = sum1[i] - sum1[mb] - 1;
        // cout << sum << endl;
        if (sum <= W)
          ub = mb;
        else
          lb = mb;
      }
    }

    {
      int lb = 0;
      int &ub = right;
      while (ub - lb > 1) {
        int mb = (lb + ub) >> 1;
        ll sum = sumL[i] - sumL[mb] - L;
        if (sum < W)
          ub = mb;
        else
          lb = mb;
      }
    }
    // find min x s.t. sum of V[i - x, i) + L * (x - 1) < W
    // cout << i << " " <<  L << "  " << left << " " << right << endl;
    if (right > left && dp[right] > dp[left] && sumL[i] - L >= W) {
      dp[i + 1] = dp[i] + 1;
    } else {
      dp[i + 1] = dp[i];
    }
  }

  bool res = false;
  REP(i, V.size()) {
    ll sum = sum1[V.size()] - sum1[i] - 1;
    if (sum <= W)
      res = res || dp[i + 1] > dp[i];
  }
  return res;
}

int main() {
  int W, N;
  while (cin >> W >> N && W) {
    vector<int> V(N);
    REP(i, N) cin >> V[i];

    int ub = W;
    int lb = 0;
    // cout << check(V, W, 1) << endl;
    while (ub - lb > 1) {
      int mb = (ub + lb) >> 1;
      if (check(V, W, mb))
        ub = mb;
      else
        lb = mb;
    }
    cout << ub << endl;
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <vector>
using namespace std;

#define REP2(i, m, n) for (int i = (int)(m); i < (int)(n); i++)
#define REP(i, n) REP2(i, 0, n)
#define ALL(c) (c).begin(), (c).end()
#define FOREACH(i, c) for (auto i = (c).begin(); i != (c).end(); ++i)
#define BIT(n, m) (((n) >> (m)) & 1)

typedef long long ll;
typedef pair<int, int> PI;

const ll inf = 1e15;
const ll mod = 1000 * 1000 * 1000 + 7;
const double eps = 1e-9;

template <typename S, typename T>
ostream &operator<<(ostream &out, const pair<S, T> &p) {
  out << "(" << p.first << ", " << p.second << ")";
  return out;
}

template <typename T> ostream &operator<<(ostream &out, const vector<T> &v) {
  out << "[";
  REP(i, v.size()) {
    if (i > 0)
      out << ", ";
    out << v[i];
  }
  out << "]";
  return out;
}

#ifndef GUARD_SEGMENT_TREE
#define GUARD_SEGMENT_TREE

#include <algorithm>
#include <limits>
#include <vector>

template <typename T> class SegTree {
  struct node_t {
    T min;
    T sum;
    T add;
    int pos;
  };

  int N;
  std::vector<T> A;
  std::vector<node_t> data;

  inline void eval(int k, int l, int r) {
    if (data[k].add == 0)
      return;

    if (r - l > 1) {
      data[2 * k + 1].add += data[k].add;
      data[2 * k + 2].add += data[k].add;
    }

    data[k].sum += data[k].add * (r - l);
    data[k].min += data[k].add;
    data[k].add = 0;
  }

  inline void merge(int k) {
    int chl = k * 2 + 1;
    int chr = k * 2 + 2;
    T lmin = data[chl].min;
    T rmin = data[chr].min;
    data[k].sum = data[chl].sum + data[chr].sum;
    data[k].min = std::min(lmin, rmin);
    data[k].pos = lmin < rmin ? data[chl].pos : data[chr].pos;
  }

  void build(int k, int l, int r) {
    if (r - l == 1) {
      data[k].min = A[l];
      data[k].sum = A[l];
      data[k].pos = l;
      data[k].add = 0;
    } else {
      int m = (l + r) / 2;
      int chl = 2 * k + 1;
      int chr = 2 * k + 2;
      build(chl, l, m);
      build(chr, m, r);
      merge(k);
    }
  }

  void add(int a, int b, T x, int k, int l, int r) {
    eval(k, l, r);
    if (b <= l || r <= a) {
      return;
    } else if (a <= l && r <= b) {
      data[k].add += x;
      eval(k, l, r);
    } else {
      int m = (l + r) / 2;
      int chl = k * 2 + 1;
      int chr = k * 2 + 2;
      add(a, b, x, chl, l, m);
      add(a, b, x, chr, m, r);
      merge(k);
    }
  }

  T min(int a, int b, int &pos, int k, int l, int r) {
    eval(k, l, r);
    if (b <= l || r <= a) {
      return std::numeric_limits<T>::max();
    } else if (a <= l && r <= b) {
      pos = data[k].pos;
      return data[k].min;
    } else {
      int m = (l + r) / 2;
      int chl = k * 2 + 1;
      int chr = k * 2 + 2;
      int lpos = -1, rpos = -1;
      T lmin = min(a, b, lpos, chl, l, m);
      T rmin = min(a, b, rpos, chr, m, r);
      merge(k);
      pos = lmin < rmin ? lpos : rpos;
      return std::min(lmin, rmin);
    }
  }

  T sum(int a, int b, int k, int l, int r) {
    eval(k, l, r);
    if (b <= l || r <= a) {
      return 0;
    } else if (a <= l && r <= b) {
      return data[k].sum;
    } else {
      int m = (l + r) / 2;
      int chl = k * 2 + 1;
      int chr = k * 2 + 2;
      T vl = sum(a, b, chl, l, m);
      T vr = sum(a, b, chr, m, r);
      merge(k);
      return vl + vr;
    }
  }

public:
  SegTree(size_t N) : N(N), A(std::vector<T>(N, 0)) {
    data.resize(4 * N);
    build(0, 0, N);
  }

  SegTree(const std::vector<T> &A) : N(A.size()), A(A) {
    data.resize(4 * N);
    build(0, 0, N);
  }

  void add(int l, int r, T x) { add(l, r, x, 0, 0, N); }
  T min(int l, int r, int &pos) {
    pos = -1;
    return min(l, r, pos, 0, 0, N);
  }
  T min(int l, int r) {
    int tmp;
    return min(l, r, tmp);
  }
  T sum(int l, int r) { return sum(l, r, 0, 0, N); }
};

#endif

bool check(const vector<int> &V, int W, int L) {
  vector<int> sum1(V.size() + 1);
  vector<int> sumL(V.size() + 1);
  REP(i, V.size()) {
    sum1[i + 1] = sum1[i] + V[i] + 1;
    sumL[i + 1] = sumL[i] + V[i] + L;
  }

  SegTree<int> dp(V.size() + 1); // dp[i] = V[0..i)???valid?????????
  dp.add(0, 1, 1);

  REP2(i, 2, V.size()) if (sumL[i] - L >= W) {
    // int llb = -1;
    // int lub =

    // find max x s.t. sum of V[i - x, i) + (x - 1) <= W
    int left = i - 2;
    int right = i - 1;
    {
      int lb = -1;
      int &ub = left;
      while (ub - lb > 1) {
        int mb = (ub + lb) >> 1;
        int sum = sum1[i] - sum1[mb] - 1;
        // cout << sum << endl;
        if (sum <= W)
          ub = mb;
        else
          lb = mb;
      }
    }

    {
      int lb = 0;
      int &ub = right;
      while (ub - lb > 1) {
        int mb = (lb + ub) >> 1;
        int sum = sumL[i] - sumL[mb] - L;
        if (sum < W)
          ub = mb;
        else
          lb = mb;
      }
    }
    // find min x s.t. sum of V[i - x, i) + L * (x - 1) < W
    // cout << i << " " <<  L << "  " << left << " " << right << endl;
    if (right > left && dp.sum(left, right) > 0) {
      dp.add(i, i + 1, 1);
    }
  }

  bool res = false;
  REP(i, V.size()) {
    int sum = sum1[V.size()] - sum1[i] - 1;
    if (sum <= W)
      res = res || dp.sum(i, i + 1) > 0;
  }
  return res;
}

int main() {
  int W, N;
  while (cin >> W >> N && W) {
    vector<int> V(N);
    REP(i, N) cin >> V[i];

    int ub = W;
    int lb = 0;
    // cout << check(V, W, 1) << endl;
    while (ub - lb > 1) {
      int mb = (ub + lb) >> 1;
      if (check(V, W, mb))
        ub = mb;
      else
        lb = mb;
    }
    cout << ub << endl;
  }
  return 0;
}