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

#include <bits/stdc++.h>
#include <ctime>
#include <iostream>
using namespace std;
#define _LL long long
#define rep(i, n) for (_LL i = 0; i < (_LL)(n); i++)
#define vecrep(itr, v) for (auto itr = (v).begin(); itr != (v).end(); itr++)

struct ModInt {
  static int _BM;
  long long int m_value;

  int getint() const { return (int)m_value; }
  void _mod() {
    if (m_value < 0)
      m_value += ((-m_value) / _BM + 1) * _BM;
    m_value %= _BM;
  }
  ModInt() { m_value = 0; }
  ModInt(int v) {
    m_value = (_LL)v;
    _mod();
  }
  ModInt(_LL v) {
    m_value = (_LL)v;
    _mod();
  }
  ModInt(const ModInt &t) { m_value = t.getint(); }
  ModInt &operator+=(int v) {
    m_value += v;
    _mod();
    return *this;
  }
  ModInt &operator-=(int v) {
    m_value -= v;
    _mod();
    return *this;
  }
  ModInt &operator*=(int v) {
    m_value *= v;
    _mod();
    return *this;
  }
  ModInt &operator+=(_LL v) { return (*this) += (int)(v % _BM); }
  ModInt &operator-=(_LL v) { return (*this) -= (int)(v % _BM); }
  ModInt &operator*=(_LL v) { return (*this) *= (int)(v % _BM); }
  ModInt &operator+=(const ModInt &t) {
    (*this) += t.getint();
    return (*this);
  }
  ModInt &operator*=(const ModInt &t) {
    (*this) *= t.getint();
    return (*this);
  }
  ModInt &operator-=(const ModInt &t) {
    (*this) -= t.getint();
    return (*this);
  }
  bool operator<(const ModInt &v) const { return m_value < v.m_value; }
  bool operator>(const ModInt &v) const { return m_value > v.m_value; }
  bool operator<=(const ModInt &v) const { return m_value <= v.m_value; }
  bool operator>=(const ModInt &v) const { return m_value >= v.m_value; }
  bool operator==(const ModInt &v) const { return m_value == v.m_value; }
  bool operator!=(const ModInt &v) const { return m_value != v.m_value; }
  bool operator<(int v) const { return m_value < v; }
  bool operator>(int v) const { return m_value > v; }
  bool operator<=(int v) const { return m_value <= v; }
  bool operator>=(int v) const { return m_value >= v; }
  bool operator==(int v) const { return m_value == v; }
  bool operator!=(int v) const { return m_value != v; }
  static int reciprocal(_LL a) {
    _LL b = _BM, u = 1, v = 0;
    while (b) {
      _LL t = a / b;
      a -= t * b;
      swap(a, b);
      u -= t * v;
      swap(u, v);
    }
    u %= _BM;
    if (u < 0)
      u += _BM;
    return (int)u;
  }
  static int reciprocal(int a) { return reciprocal((_LL)a); }

  ModInt &operator/=(const ModInt &t) {
    (*this) /= t.getint();
    return (*this);
  }
  ModInt &operator/=(int v) {
    (*this) *= reciprocal(v);
    return *this;
  }
  ModInt &operator/=(_LL v) {
    (*this) *= reciprocal(v);
    return *this;
  }
  const ModInt operator+(const ModInt &t) const {
    ModInt ans(*this);
    return ans += t;
  }
  const ModInt operator+(int t) const {
    ModInt ans(*this);
    return ans += t;
  }
  const ModInt operator+(_LL t) const {
    ModInt ans(*this);
    return ans += t;
  }
  const ModInt operator-(const ModInt &t) const {
    ModInt ans(*this);
    return ans -= t;
  }
  const ModInt operator-(int t) const {
    ModInt ans(*this);
    return ans -= t;
  }
  const ModInt operator-(_LL t) const {
    ModInt ans(*this);
    return ans -= t;
  }
  const ModInt operator*(const ModInt &t) const {
    ModInt ans(*this);
    return ans *= t;
  }
  const ModInt operator*(int t) const {
    ModInt ans(*this);
    return ans *= t;
  }
  const ModInt operator*(_LL t) const {
    ModInt ans(*this);
    return ans *= t;
  }
  const ModInt operator/(const ModInt &t) const {
    ModInt ans(*this);
    return ans /= t;
  }
  const ModInt operator/(int t) const {
    ModInt ans(*this);
    return ans /= t;
  }
  const ModInt operator/(_LL t) const {
    ModInt ans(*this);
    return ans /= t;
  }

  bool operator==(int t) { return getint() == t; }

  static int modadd(int a, int b) {
    ModInt t(a);
    t += b;
    return t.getint();
  }
  static int modminus(int a, int b) {
    ModInt t(a);
    t -= b;
    return t.getint();
  }
  static int modmul(int a, int b) {
    ModInt t(a);
    t *= b;
    return t.getint();
  }
  static int modadd(_LL a, _LL b) {
    ModInt t(a);
    t += b;
    return t.getint();
  }
  static int modminus(_LL a, _LL b) {
    ModInt t(a);
    t -= b;
    return t.getint();
  }
  static int modmul(_LL a, _LL b) {
    ModInt t(a);
    t *= b;
    return t.getint();
  }
  static int modpow(int a, int b) { return modpow((_LL)a, (_LL)b); }
  static int modpow(_LL a, _LL b) {
    ModInt ans(1);
    int heap[64];
    heap[0] = (a % _BM);
    for (int bit = 0; b >= (((_LL)1) << bit); bit++) {
      if (bit > 0)
        heap[bit] = modmul(heap[bit - 1], heap[bit - 1]);
      if (b & (((_LL)1) << bit)) {
        ans *= heap[bit];
      }
    }
    return ans.getint();
  }

  static int getCombination(_LL n, _LL r) {
    _LL ans;
    ans = 1;
    for (_LL i = 0; i < r; i++)
      ans = modmul(ans, n - i);
    _LL inv = 1;
    for (_LL i = 0; i < r; i++)
      inv = modmul(inv, i + 1);
    return modmul(ans, (_LL)reciprocal(inv));
  }

  static int combination(int n, int r) {
    int *fac = (int *)malloc(sizeof(int) * (n + 1));
    int *facinv = (int *)malloc(sizeof(int) * (n + 1));
    fac[0] = 1;
    for (int k = 1; k <= n; k++)
      fac[k] = modmul(k, fac[k - 1]);
    facinv[n] = reciprocal(fac[n]);
    for (int k = n; k > 0; k--)
      facinv[k - 1] = modmul(k, facinv[k]);

    ModInt ans(fac[n]);
    ans *= facinv[r];
    ans *= facinv[n - r];

    free(fac);
    free(facinv);
    return ans.getint();
  }
};

int ModInt::_BM = 998244353;

int main() {
  int n, k;
  cin >> n >> k;
  vector<ModInt> dp(n);
  vector<pair<int, int>> list(k);
  rep(i, k) cin >> list[i].first >> list[i].second;
  sort(list.begin(), list.end());
  ModInt sum = 0;
  rep(i, n) {
    if (i == 0) {
      dp[0] = 1;
    } else {
      dp[i] = sum;
    }
    rep(j, k) {
      if (list[j].first > i + 1)
        break;
      int addindex = i + 1 - list[j].first;
      int removeindex = i - list[j].second;
      sum += dp[addindex];
      if (removeindex >= 0)
        sum -= dp[removeindex];
    }
  }
  cout << dp[n - 1].getint() << endl;

  return 0;
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>
#include <ctime>
#include <iostream>
using namespace std;
#define _LL long long
#define rep(i, n) for (_LL i = 0; i < (_LL)(n); i++)
#define vecrep(itr, v) for (auto itr = (v).begin(); itr != (v).end(); itr++)

template <class T> class SegTree {
private:
  int _n;
  int _d;

  template <class U> class SNode {
  public:
    U _min;
    U _max;
    U _sum;
    U _value;
    U _add;
    U _mul;
    bool _used;
    bool _last;

    SNode() {
      _min = 0;
      _max = 0;
      _sum = 0;
      _value = 0;
      _add = 0;
      _mul = 1;
      _used = false;
      _last = false;
    }

    SNode(const SNode<U> &t) { set(t); }

    void set(const SNode<U> &t) {
      _min = t._min;
      _max = t._max;
      _sum = t._sum;
      _value = t._value;
      _add = t._add;
      _mul = t._mul;
      _used = t._used;
      _last = t._last;
    }

    void set(U v) {
      _min = v;
      _max = v;
      _sum = v;
      _value = v;
      _add = 0;
      _mul = 1;
      _last = true;
      _used = true;
    }

    void set(U v, int d) {
      _min = v;
      _max = v;
      _sum = v * (1 << d);
      _value = v;
      _add = 0;
      _mul = 1;
      _last = true;
      _used = true;
    }
  };

  SNode<T> *nodes;

  int dindex(int d) { return (1 << d); }

  T calcvalue(int index, T v, int num = 1) {
    T ret = v * nodes[index]._mul + nodes[index]._add * num;
    return ret;
  }
  T getnodemin(int index) {
    return calcvalue(index, nodes[index]._mul < 0 ? nodes[index]._max
                                                  : nodes[index]._min);
  }
  T getnodemax(int index) {
    return calcvalue(index, nodes[index]._mul >= 0 ? nodes[index]._max
                                                   : nodes[index]._min);
  }
  T getnodesum(int index, int d) {
    return calcvalue(index, nodes[index]._sum, 1 << (_d - 1 - d));
  }
  T getvalue(int index) { return calcvalue(index, nodes[index]._value); }

  void evalnode(int index, int d) {
    if (index < 1)
      return;
    nodes[index]._used = true;
    if (d == _d - 1) {
      nodes[index]._min = getvalue(index);
      nodes[index]._max = getvalue(index);
      nodes[index]._sum = getvalue(index);
    } else if (nodes[index * 2]._used && nodes[index * 2 + 1]._used) {
      nodes[index]._min = min(getnodemin(2 * index), getnodemin(2 * index + 1));
      nodes[index]._max = max(getnodemax(2 * index), getnodemax(2 * index + 1));
      nodes[index]._sum =
          getnodesum(2 * index, d + 1) + getnodesum(2 * index + 1, d + 1);
    } else if (nodes[index * 2]._used) {
      nodes[index]._min = getnodemin(2 * index);
      nodes[index]._max = getnodemax(2 * index);
      nodes[index]._sum = getnodesum(2 * index, d + 1);
    } else if (nodes[index * 2 + 1]._used) {
      nodes[index]._min = getnodemin(2 * index + 1);
      nodes[index]._max = getnodemax(2 * index + 1);
      nodes[index]._sum = getnodesum(2 * index + 1, d + 1);
    }
  }

  // 対象ノードが範囲に含まれるか　-1:
  // 含まれない、　0:部分的に含まれる、1:完全に含む
  int check(int l, int r, int index, int d) {
    int i = index - (1 << d);
    int k = (1 << (_d - d - 1));
    if (r <= i * k || l >= (i + 1) * k)
      return -1;
    if (l <= i * k && r >= (i + 1) * k)
      return 1;
    return 0;
  }

  T getsub_minmax(int l, int r, int index, int d, T m) {
    if (m >= 0) {
      if (check(l, r, index * 2, d + 1) == -1)
        return getmaxsub(l, r, 2 * index + 1, d + 1);
      if (check(l, r, index * 2 + 1, d + 1) == -1)
        return getmaxsub(l, r, 2 * index, d + 1);
      return max(getmaxsub(l, r, 2 * index, d + 1),
                 getmaxsub(l, r, 2 * index + 1, d + 1));
    } else {
      if (check(l, r, index * 2, d + 1) == -1)
        return getminsub(l, r, 2 * index + 1, d + 1);
      if (check(l, r, index * 2 + 1, d + 1) == -1)
        return getminsub(l, r, 2 * index, d + 1);
      return min(getminsub(l, r, 2 * index, d + 1),
                 getminsub(l, r, 2 * index + 1, d + 1));
    }
  }

  T getminsub(int l, int r, int index, int d) {
    if (d == _d - 1 || nodes[index]._last)
      return getnodemin(index);
    if (check(l, r, index, d) == 1)
      return getnodemin(index);
    T ret = calcvalue(index, getsub_minmax(l, r, index, d, -nodes[index]._mul));
    return ret;
  }

  T getmaxsub(int l, int r, int index, int d) {
    if (d == _d - 1 || nodes[index]._last)
      return getnodemax(index);
    if (check(l, r, index, d) == 1)
      return getnodemax(index);
    T ret = calcvalue(index, getsub_minmax(l, r, index, d, nodes[index]._mul));
    return ret;
  }

  T getsumsub(int l, int r, int index, int d) {
    if (d == _d - 1)
      return getnodesum(index, d);
    int i = index - (1 << d);
    int k = (1 << (_d - d - 1));
    if (nodes[index]._last)
      return calcvalue(index, nodes[index]._value) *
             (min(r, (i + 1) * k) - max(l, i * k));
    if (check(l, r, index, d) == 1)
      return getnodesum(index, d);
    T ret = 0;
    int n1 = min(r, i * k + k / 2) - max(l, i * k);
    int n2 = min(r, i * k + k) - max(l, i * k + k / 2);
    if (n1 > 0)
      ret += calcvalue(index, getsumsub(l, r, 2 * index, d + 1), n1);
    if (n2 > 0)
      ret += calcvalue(index, getsumsub(l, r, 2 * index + 1, d + 1), n2);
    return ret;
  }

  void denpan(int index, int d) {
    nodes[index]._last = false;
    T pre = getvalue(index);
    setRangeSub(0, _n, index * 2, d + 1, pre);
    setRangeSub(0, _n, index * 2 + 1, d + 1, pre);
    nodes[index]._add = 0;
    nodes[index]._mul = 1;
  }

  void calcdenpan(int index, int d) {
    T premul = nodes[index]._mul;
    T preadd = nodes[index]._add;
    if (premul != 1) {
      mulRangeSub(0, _n, index * 2, d + 1, premul);
      mulRangeSub(0, _n, index * 2 + 1, d + 1, premul);
    }
    if (preadd != 0) {
      addRangeSub(0, _n, index * 2, d + 1, preadd);
      addRangeSub(0, _n, index * 2 + 1, d + 1, preadd);
    }
    nodes[index]._mul = 1;
    nodes[index]._add = 0;
  }

  void setRangeSub(int l, int r, int index, int d, T v) {
    if (d == _d - 1 || check(l, r, index, d) == 1) {
      nodes[index].set(v, _d - 1 - d);
      return;
    }
    if (nodes[index]._last)
      denpan(index, d);
    calcdenpan(index, d);
    if (check(l, r, index * 2, d + 1) != -1)
      setRangeSub(l, r, index * 2, d + 1, v);
    if (check(l, r, index * 2 + 1, d + 1) != -1)
      setRangeSub(l, r, index * 2 + 1, d + 1, v);
    evalnode(index, d);
  }

  void addRangeSub(int l, int r, int index, int d, T v) {
    if (d == _d - 1 || check(l, r, index, d) == 1) {
      nodes[index]._add += v;
      return;
    }
    if (nodes[index]._last)
      denpan(index, d);
    if (nodes[index]._mul != 1)
      calcdenpan(index, d);
    if (check(l, r, index * 2, d + 1) != -1)
      addRangeSub(l, r, index * 2, d + 1, v);
    if (check(l, r, index * 2 + 1, d + 1) != -1)
      addRangeSub(l, r, index * 2 + 1, d + 1, v);
    evalnode(index, d);
  }

  void mulRangeSub(int l, int r, int index, int d, T v) {
    if (d == _d - 1 || check(l, r, index, d) == 1) {
      nodes[index]._mul *= v;
      nodes[index]._add *= v;
      return;
    }
    if (nodes[index]._last)
      denpan(index, d);
    if (nodes[index]._add != 0)
      calcdenpan(index, d);
    if (check(l, r, index * 2, d + 1) != -1)
      mulRangeSub(l, r, index * 2, d + 1, v);
    if (check(l, r, index * 2 + 1, d + 1) != -1)
      mulRangeSub(l, r, index * 2 + 1, d + 1, v);
    evalnode(index, d);
  }

  T getSub(int i, int index, int d) {
    if (d == _d - 1 || nodes[index]._last || !nodes[index]._used)
      return getvalue(index);
    if (check(i, i + 1, index * 2, d + 1) != -1)
      return calcvalue(index, getSub(i, 2 * index, d + 1));
    return calcvalue(index, getSub(i, 2 * index + 1, d + 1));
  }

public:
  SegTree(int n) {
    _n = n;
    _d = 1;
    int bit = 1;
    while (bit < _n) {
      bit *= 2;
      _d++;
    }
    nodes = new SNode<T>[bit * 2];
    for (int i = 0; i < n; i++)
      nodes[bit + i]._used = true;
    for (int i = bit - 1; i >= 0; i--)
      nodes[i]._used = (nodes[i * 2]._used || nodes[i * 2 + 1]._used);
  }

  ~SegTree() { delete nodes; }

  void set(int i, T value) { setRangeSub(i, i + 1, 1, 0, value); }

  T get(int i) { return getSub(i, 1, 0); }

  // l <= i < r
  void setRange(int l, int r, T value) { setRangeSub(l, r, 1, 0, value); }

  void addRange(int l, int r, T value) { addRangeSub(l, r, 1, 0, value); }

  void mulRange(int l, int r, T value) { mulRangeSub(l, r, 1, 0, value); }

  T getmin(int l, int r) { return getminsub(l, r, 1, 0); }

  T getmax(int l, int r) { return getmaxsub(l, r, 1, 0); }

  T getsum(int l, int r) { return getsumsub(l, r, 1, 0); }
};

struct ModInt {
  static int _BM;
  long long int m_value;

  int getint() const { return (int)m_value; }
  void _mod() {
    if (m_value < 0)
      m_value += ((-m_value) / _BM + 1) * _BM;
    m_value %= _BM;
  }
  ModInt() { m_value = 0; }
  ModInt(int v) {
    m_value = (_LL)v;
    _mod();
  }
  ModInt(_LL v) {
    m_value = (_LL)v;
    _mod();
  }
  ModInt(const ModInt &t) { m_value = t.getint(); }
  ModInt &operator+=(int v) {
    m_value += v;
    _mod();
    return *this;
  }
  ModInt &operator-=(int v) {
    m_value -= v;
    _mod();
    return *this;
  }
  ModInt &operator*=(int v) {
    m_value *= v;
    _mod();
    return *this;
  }
  ModInt &operator+=(_LL v) { return (*this) += (int)(v % _BM); }
  ModInt &operator-=(_LL v) { return (*this) -= (int)(v % _BM); }
  ModInt &operator*=(_LL v) { return (*this) *= (int)(v % _BM); }
  ModInt &operator+=(const ModInt &t) {
    (*this) += t.getint();
    return (*this);
  }
  ModInt &operator*=(const ModInt &t) {
    (*this) *= t.getint();
    return (*this);
  }
  ModInt &operator-=(const ModInt &t) {
    (*this) -= t.getint();
    return (*this);
  }
  bool operator<(const ModInt &v) const { return m_value < v.m_value; }
  bool operator>(const ModInt &v) const { return m_value > v.m_value; }
  bool operator<=(const ModInt &v) const { return m_value <= v.m_value; }
  bool operator>=(const ModInt &v) const { return m_value >= v.m_value; }
  bool operator==(const ModInt &v) const { return m_value == v.m_value; }
  bool operator!=(const ModInt &v) const { return m_value != v.m_value; }
  bool operator<(int v) const { return m_value < v; }
  bool operator>(int v) const { return m_value > v; }
  bool operator<=(int v) const { return m_value <= v; }
  bool operator>=(int v) const { return m_value >= v; }
  bool operator==(int v) const { return m_value == v; }
  bool operator!=(int v) const { return m_value != v; }
  static int reciprocal(_LL a) {
    _LL b = _BM, u = 1, v = 0;
    while (b) {
      _LL t = a / b;
      a -= t * b;
      swap(a, b);
      u -= t * v;
      swap(u, v);
    }
    u %= _BM;
    if (u < 0)
      u += _BM;
    return (int)u;
  }
  static int reciprocal(int a) { return reciprocal((_LL)a); }

  ModInt &operator/=(const ModInt &t) {
    (*this) /= t.getint();
    return (*this);
  }
  ModInt &operator/=(int v) {
    (*this) *= reciprocal(v);
    return *this;
  }
  ModInt &operator/=(_LL v) {
    (*this) *= reciprocal(v);
    return *this;
  }
  const ModInt operator+(const ModInt &t) const {
    ModInt ans(*this);
    return ans += t;
  }
  const ModInt operator+(int t) const {
    ModInt ans(*this);
    return ans += t;
  }
  const ModInt operator+(_LL t) const {
    ModInt ans(*this);
    return ans += t;
  }
  const ModInt operator-(const ModInt &t) const {
    ModInt ans(*this);
    return ans -= t;
  }
  const ModInt operator-(int t) const {
    ModInt ans(*this);
    return ans -= t;
  }
  const ModInt operator-(_LL t) const {
    ModInt ans(*this);
    return ans -= t;
  }
  const ModInt operator*(const ModInt &t) const {
    ModInt ans(*this);
    return ans *= t;
  }
  const ModInt operator*(int t) const {
    ModInt ans(*this);
    return ans *= t;
  }
  const ModInt operator*(_LL t) const {
    ModInt ans(*this);
    return ans *= t;
  }
  const ModInt operator/(const ModInt &t) const {
    ModInt ans(*this);
    return ans /= t;
  }
  const ModInt operator/(int t) const {
    ModInt ans(*this);
    return ans /= t;
  }
  const ModInt operator/(_LL t) const {
    ModInt ans(*this);
    return ans /= t;
  }

  bool operator==(int t) { return getint() == t; }

  static int modadd(int a, int b) {
    ModInt t(a);
    t += b;
    return t.getint();
  }
  static int modminus(int a, int b) {
    ModInt t(a);
    t -= b;
    return t.getint();
  }
  static int modmul(int a, int b) {
    ModInt t(a);
    t *= b;
    return t.getint();
  }
  static int modadd(_LL a, _LL b) {
    ModInt t(a);
    t += b;
    return t.getint();
  }
  static int modminus(_LL a, _LL b) {
    ModInt t(a);
    t -= b;
    return t.getint();
  }
  static int modmul(_LL a, _LL b) {
    ModInt t(a);
    t *= b;
    return t.getint();
  }
  static int modpow(int a, int b) { return modpow((_LL)a, (_LL)b); }
  static int modpow(_LL a, _LL b) {
    ModInt ans(1);
    int heap[64];
    heap[0] = (a % _BM);
    for (int bit = 0; b >= (((_LL)1) << bit); bit++) {
      if (bit > 0)
        heap[bit] = modmul(heap[bit - 1], heap[bit - 1]);
      if (b & (((_LL)1) << bit)) {
        ans *= heap[bit];
      }
    }
    return ans.getint();
  }

  static int getCombination(_LL n, _LL r) {
    _LL ans;
    ans = 1;
    for (_LL i = 0; i < r; i++)
      ans = modmul(ans, n - i);
    _LL inv = 1;
    for (_LL i = 0; i < r; i++)
      inv = modmul(inv, i + 1);
    return modmul(ans, (_LL)reciprocal(inv));
  }

  static int combination(int n, int r) {
    int *fac = (int *)malloc(sizeof(int) * (n + 1));
    int *facinv = (int *)malloc(sizeof(int) * (n + 1));
    fac[0] = 1;
    for (int k = 1; k <= n; k++)
      fac[k] = modmul(k, fac[k - 1]);
    facinv[n] = reciprocal(fac[n]);
    for (int k = n; k > 0; k--)
      facinv[k - 1] = modmul(k, facinv[k]);

    ModInt ans(fac[n]);
    ans *= facinv[r];
    ans *= facinv[n - r];

    free(fac);
    free(facinv);
    return ans.getint();
  }
};

int ModInt::_BM = 998244353;

int main() {
  int n, k;
  cin >> n >> k;
  SegTree<ModInt> st(n);
  st.set(0, ModInt(1));

  vector<pair<int, int>> list(k);
  rep(i, k) cin >> list[i].first >> list[i].second;

  for (int i = 0; i < n; i++) {
    ModInt v = st.get(i);
    rep(j, k) {
      if (i + list[j].first >= n)
        continue;
      st.addRange(i + list[j].first, min(n, i + list[j].second + 1), v);
    }
  }

  cout << st.get(n - 1).getint() << endl;
  return 0;
}