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

#define __USE_MINGW_ANSI_STDIO 0
#include <bits/stdc++.h>

using namespace std;
using ll = long long;
#define int ll
using VI = vector<int>;
using VVI = vector<VI>;
using PII = pair<int, int>;

#define FOR(i, a, n) for (ll i = (ll)a; i < (ll)n; ++i)
#define REP(i, n) FOR(i, 0, n)
#define ALL(x) x.begin(), x.end()
#define PB push_back

const ll LLINF = (1LL << 60);
const int INF = (1LL << 30);
const int MOD = 1000000007;

template <typename T> T &chmin(T &a, const T &b) { return a = min(a, b); }
template <typename T> T &chmax(T &a, const T &b) { return a = max(a, b); }
template <typename T> bool IN(T a, T b, T x) { return a <= x && x < b; }
template <typename T> T ceil(T a, T b) { return a / b + !!(a % b); }
template <class S, class T>
ostream &operator<<(ostream &out, const pair<S, T> &a) {
  out << '(' << a.first << ',' << a.second << ')';
  return out;
}
template <class T> ostream &operator<<(ostream &out, const vector<T> &a) {
  out << '[';
  REP(i, a.size()) {
    out << a[i];
    if (i != a.size() - 1)
      out << ',';
  }
  out << ']';
  return out;
}

int dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0};

// 遅延セグメントツリー
template <typename T, typename E> struct segtree {
  using F = function<T(T, T)>;
  using G = function<T(T, E)>;
  using H = function<E(E, E)>;
  using P = function<E(E, int)>;
  F f;
  G g;
  H h;
  P p;
  T d1;
  E d0;
  int n;
  vector<T> dat;
  vector<E> lazy;

  segtree() {}
  segtree(
      int n_, F f_, G g_, H h_, T d1_, E d0_,
      P p_ = [](E a, int b) { return a; })
      : f(f_), g(g_), h(h_), p(p_), d1(d1_), d0(d0_) {
    n = 1;
    while (n < n_)
      n *= 2;
    dat.assign(n * 2, d1);
    lazy.assign(n * 2, d0);
  }
  void build(vector<T> v) {
    REP(i, v.size()) dat[i + n - 1] = v[i];
    for (int i = n - 2; i >= 0; --i)
      dat[i] = f(dat[i * 2 + 1], dat[i * 2 + 2]);
  }

  // 区間の幅がlenの節点kについて遅延評価
  inline void eval(int len, int k) {
    if (lazy[k] == d0)
      return;
    if (k * 2 + 1 < n * 2 - 1) {
      lazy[2 * k + 1] = h(lazy[k * 2 + 1], lazy[k]);
      lazy[2 * k + 2] = h(lazy[k * 2 + 2], lazy[k]);
    }
    dat[k] = g(dat[k], p(lazy[k], len));
    lazy[k] = d0;
  }
  // [a, b)
  T update(int a, int b, E x, int k, int l, int r) {
    eval(r - l, k);
    if (b <= l || r <= a)
      return dat[k];
    if (a <= l && r <= b) {
      lazy[k] = h(lazy[k], x);
      return g(dat[k], p(lazy[k], r - l));
    }
    return dat[k] = f(update(a, b, x, 2 * k + 1, l, (l + r) / 2),
                      update(a, b, x, 2 * k + 2, (l + r) / 2, r));
  }
  T update(int a, int b, E x) { return update(a, b, x, 0, 0, n); }
  // [a, b)
  T query(int a, int b, int k, int l, int r) {
    eval(r - l, k);
    if (a <= l && r <= b)
      return dat[k];
    bool left = !((l + r) / 2 <= a || b <= l),
         right = !(r <= 1 || b <= (l + r) / 2);
    if (left && right)
      return f(query(a, b, 2 * k + 1, l, (l + r) / 2),
               query(a, b, 2 * k + 2, (l + r) / 2, r));
    if (left)
      return query(a, b, 2 * k + 1, l, (l + r) / 2);
    return query(a, b, 2 * k + 2, (l + r) / 2, r);
  }
  T query(int a, int b) { return query(a, b, 0, 0, n); }
  // デバッグ出力
  void debug() {
    cout << "---------------------" << endl;
    int cnt = 0;
    for (int i = 1; i <= n; i *= 2) {
      REP(j, i) {
        cout << "(" << dat[cnt] << "," << lazy[cnt] << ") ";
        cnt++;
      }
      cout << endl;
    }
    cout << "---------------------" << endl;
  }
};

struct node {
  int ma, mi, macnt, micnt;
};

signed main(void) {
  int H, W, q;
  scanf("%lld%lld%lld", &H, &W, &q);
  VI a(H), b(W);
  REP(i, H) scanf("%lld", &a[i]);
  REP(i, W) scanf("%lld", &b[i]);

  auto f = [](VI a, VI b) {
    // max,minの数
    int maxnum = a[0] == max(a[0], b[0]) ? a[1] : 0;
    maxnum += b[0] == max(a[0], b[0]) ? b[1] : 0;
    int minnum = a[2] == min(a[2], b[2]) ? a[3] : 0;
    minnum += b[2] == min(a[2], b[2]) ? b[3] : 0;
    return VI{max(a[0], b[0]), maxnum, min(a[2], b[2]), minnum};
  };
  auto g = [](VI a, int b) { return VI{a[0] + b, a[1], a[2] + b, a[3]}; };
  auto h = [](int a, int b) { return a + b; };
  segtree<VI, int> seg1(H, f, g, h, {0, 1, 0, 1}, 0),
      seg2(W, f, g, h, {0, 1, 0, 1}, 0);

  VVI inita, initb;
  REP(i, H) inita.PB({a[i], 1, a[i], 1});
  REP(i, W) initb.PB({b[i], 1, b[i], 1});
  seg1.build(inita);
  seg2.build(initb);

  // seg1.debug();
  // seg2.debug();

  REP(i, q) {
    int type;
    scanf("%lld", &type);
    if (type == 1) {
      int a, b, v;
      scanf("%lld%lld%lld", &a, &b, &v);
      seg1.update(a - 1, b, v);
    } else if (type == 2) {
      int a, b, v;
      scanf("%lld%lld%lld", &a, &b, &v);
      seg2.update(a - 1, b, v);
    } else if (type == 4) {
      int ma = -LLINF, num = 0;
      int a, b, c, d;
      scanf("%lld%lld%lld%lld", &a, &b, &c, &d);
      VI v1 = seg1.query(a - 1, b);
      VI v2 = seg2.query(c - 1, d);
      ma = max({v1[0] * v2[0], v1[2] * v2[2], v1[0] * v2[2], v1[2] * v2[0]});
      // maxが0のケース
      if (ma == 0) {
        int tmpa = 0, tmpb = 0;
        if (v1[0] == 0)
          tmpa = v1[1];
        if (v1[2] == 0)
          tmpa = v1[3];
        if (v2[0] == 0)
          tmpb = v2[1];
        if (v2[2] == 0)
          tmpb = v2[3];
        num =
            (b - a + 1) * (d - c + 1) - (b - a + 1 - tmpa) * (d - c + 1 - tmpb);
      } else {
        if (v1[0] == v1[2] && v2[0] == v2[2]) {
          num = (b - a + 1) * (d - c + 1);
        } else if (v1[0] == v1[2] || v2[0] == v2[2]) {
          if (v1[2] * v2[2] == ma)
            num += v1[3] * v2[3];
          if (v1[0] * v2[0] == ma)
            num += v1[1] * v2[1];
        } else {
          if (v1[0] * v2[0] == ma)
            num += v1[1] * v2[1];
          if (v1[0] * v2[2] == ma)
            num += v1[1] * v2[3];
          if (v1[2] * v2[0] == ma)
            num += v1[3] * v2[1];
          if (v1[2] * v2[2] == ma)
            num += v1[3] * v2[3];
        }
      }
      printf("%lld %lld\\n", ma, num);
    } else if (type == 3) {
      int mi = LLINF, num = 0;
      int a, b, c, d;
      scanf("%lld%lld%lld%lld", &a, &b, &c, &d);
      VI v1 = seg1.query(a - 1, b);
      VI v2 = seg2.query(c - 1, d);
      mi = min({v1[0] * v2[0], v1[2] * v2[2], v1[0] * v2[2], v1[2] * v2[0]});
      // minが0の場合
      if (mi == 0) {
        int tmpa = 0, tmpb = 0;
        if (v1[0] == 0)
          tmpa = v1[1];
        if (v1[2] == 0)
          tmpa = v1[3];
        if (v2[0] == 0)
          tmpb = v2[1];
        if (v2[2] == 0)
          tmpb = v2[3];
        num =
            (b - a + 1) * (d - c + 1) - (b - a + 1 - tmpa) * (d - c + 1 - tmpb);
      } else {
        if (v1[0] == v1[2] && v2[0] == v2[2]) {
          num = (b - a + 1) * (d - c + 1);
        } else if (v1[0] == v1[2] || v2[0] == v2[2]) {
          if (v1[2] * v2[2] == mi)
            num += v1[3] * v2[3];
          if (v1[0] * v2[0] == mi)
            num += v1[1] * v2[1];
        } else {
          if (v1[0] * v2[0] == mi)
            num += v1[1] * v2[1];
          if (v1[0] * v2[2] == mi)
            num += v1[1] * v2[3];
          if (v1[2] * v2[0] == mi)
            num += v1[3] * v2[1];
          if (v1[2] * v2[2] == mi)
            num += v1[3] * v2[3];
        }
      }
      printf("%lld %lld\\n", mi, num);
    }
    // seg1.debug();
    // seg2.debug();
  }

  return 0;
}


Error: TLE

Fixed submission:

#define __USE_MINGW_ANSI_STDIO 0
#include <bits/stdc++.h>

using namespace std;
using ll = long long;
#define int ll
using VI = vector<int>;
using VVI = vector<VI>;
using PII = pair<int, int>;

#define FOR(i, a, n) for (ll i = (ll)a; i < (ll)n; ++i)
#define REP(i, n) FOR(i, 0, n)
#define ALL(x) x.begin(), x.end()
#define PB push_back

const ll LLINF = (1LL << 60);
const int INF = (1LL << 30);
const int MOD = 1000000007;

template <typename T> T &chmin(T &a, const T &b) { return a = min(a, b); }
template <typename T> T &chmax(T &a, const T &b) { return a = max(a, b); }
template <typename T> bool IN(T a, T b, T x) { return a <= x && x < b; }
template <typename T> T ceil(T a, T b) { return a / b + !!(a % b); }
template <class S, class T>
ostream &operator<<(ostream &out, const pair<S, T> &a) {
  out << '(' << a.first << ',' << a.second << ')';
  return out;
}
template <class T> ostream &operator<<(ostream &out, const vector<T> &a) {
  out << '[';
  REP(i, a.size()) {
    out << a[i];
    if (i != a.size() - 1)
      out << ',';
  }
  out << ']';
  return out;
}

int dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0};

// 遅延セグメントツリー
template <typename T, typename E> struct segtree {
  using F = function<T(T, T)>;
  using G = function<T(T, E)>;
  using H = function<E(E, E)>;
  using P = function<E(E, int)>;
  F f;
  G g;
  H h;
  P p;
  T d1;
  E d0;
  int n;
  vector<T> dat;
  vector<E> lazy;

  segtree() {}
  segtree(
      int n_, F f_, G g_, H h_, T d1_, E d0_,
      P p_ = [](E a, int b) { return a; })
      : f(f_), g(g_), h(h_), p(p_), d1(d1_), d0(d0_) {
    n = 1;
    while (n < n_)
      n *= 2;
    dat.assign(n * 2, d1);
    lazy.assign(n * 2, d0);
  }
  void build(vector<T> v) {
    REP(i, v.size()) dat[i + n - 1] = v[i];
    for (int i = n - 2; i >= 0; --i)
      dat[i] = f(dat[i * 2 + 1], dat[i * 2 + 2]);
  }

  // 区間の幅がlenの節点kについて遅延評価
  inline void eval(int len, int k) {
    if (lazy[k] == d0)
      return;
    if (k * 2 + 1 < n * 2 - 1) {
      lazy[2 * k + 1] = h(lazy[k * 2 + 1], lazy[k]);
      lazy[2 * k + 2] = h(lazy[k * 2 + 2], lazy[k]);
    }
    dat[k] = g(dat[k], p(lazy[k], len));
    lazy[k] = d0;
  }
  // [a, b)
  T update(int a, int b, E x, int k, int l, int r) {
    eval(r - l, k);
    if (b <= l || r <= a)
      return dat[k];
    if (a <= l && r <= b) {
      lazy[k] = h(lazy[k], x);
      return g(dat[k], p(lazy[k], r - l));
    }
    return dat[k] = f(update(a, b, x, 2 * k + 1, l, (l + r) / 2),
                      update(a, b, x, 2 * k + 2, (l + r) / 2, r));
  }
  T update(int a, int b, E x) { return update(a, b, x, 0, 0, n); }
  // [a, b)
  T query(int a, int b, int k, int l, int r) {
    eval(r - l, k);
    if (a <= l && r <= b)
      return dat[k];
    bool left = !((l + r) / 2 <= a || b <= l),
         right = !(r <= 1 || b <= (l + r) / 2);
    if (left && right)
      return f(query(a, b, 2 * k + 1, l, (l + r) / 2),
               query(a, b, 2 * k + 2, (l + r) / 2, r));
    if (left)
      return query(a, b, 2 * k + 1, l, (l + r) / 2);
    return query(a, b, 2 * k + 2, (l + r) / 2, r);
  }
  T query(int a, int b) { return query(a, b, 0, 0, n); }
  // デバッグ出力
  void debug() {
    cout << "---------------------" << endl;
    int cnt = 0;
    for (int i = 1; i <= n; i *= 2) {
      REP(j, i) {
        cout << "(" << dat[cnt] << "," << lazy[cnt] << ") ";
        cnt++;
      }
      cout << endl;
    }
    cout << "---------------------" << endl;
  }
};

struct node {
  int ma, mi, macnt, micnt;
};

signed main(void) {
  int H, W, q;
  scanf("%lld%lld%lld", &H, &W, &q);
  VI a(H), b(W);
  REP(i, H) scanf("%lld", &a[i]);
  REP(i, W) scanf("%lld", &b[i]);

  auto f = [](VI a, VI b) {
    // max,minの数
    int maxnum = a[0] == max(a[0], b[0]) ? a[1] : 0;
    maxnum += b[0] == max(a[0], b[0]) ? b[1] : 0;
    int minnum = a[2] == min(a[2], b[2]) ? a[3] : 0;
    minnum += b[2] == min(a[2], b[2]) ? b[3] : 0;
    return VI{max(a[0], b[0]), maxnum, min(a[2], b[2]), minnum};
  };
  auto g = [](VI a, VI b) { return VI{a[0] + b[0], a[1], a[2] + b[2], a[3]}; };
  auto h = [](VI a, VI b) { return VI{a[0] + b[0], a[1], a[2] + b[2], a[3]}; };
  segtree<VI, VI> seg1(H, f, g, h, {0, 1, 0, 1}, {0, 0, 0, 0}),
      seg2(W, f, g, h, {0, 1, 0, 1}, {0, 0, 0, 0});

  VVI inita, initb;
  REP(i, H) inita.PB({a[i], 1, a[i], 1});
  REP(i, W) initb.PB({b[i], 1, b[i], 1});
  seg1.build(inita);
  seg2.build(initb);

  // seg1.debug();
  // seg2.debug();

  REP(i, q) {
    int type;
    scanf("%lld", &type);
    if (type == 1) {
      int a, b, v;
      scanf("%lld%lld%lld", &a, &b, &v);
      seg1.update(a - 1, b, {v, 0, v, 0});
    } else if (type == 2) {
      int a, b, v;
      scanf("%lld%lld%lld", &a, &b, &v);
      seg2.update(a - 1, b, {v, 0, v, 0});
    } else if (type == 4) {
      int ma = -LLINF, num = 0;
      int a, b, c, d;
      scanf("%lld%lld%lld%lld", &a, &b, &c, &d);
      VI v1 = seg1.query(a - 1, b);
      VI v2 = seg2.query(c - 1, d);
      ma = max({v1[0] * v2[0], v1[2] * v2[2], v1[0] * v2[2], v1[2] * v2[0]});
      // maxが0のケース
      if (ma == 0) {
        int tmpa = 0, tmpb = 0;
        if (v1[0] == 0)
          tmpa = v1[1];
        if (v1[2] == 0)
          tmpa = v1[3];
        if (v2[0] == 0)
          tmpb = v2[1];
        if (v2[2] == 0)
          tmpb = v2[3];
        num =
            (b - a + 1) * (d - c + 1) - (b - a + 1 - tmpa) * (d - c + 1 - tmpb);
      } else {
        if (v1[0] == v1[2] && v2[0] == v2[2]) {
          num = (b - a + 1) * (d - c + 1);
        } else if (v1[0] == v1[2] || v2[0] == v2[2]) {
          if (v1[2] * v2[2] == ma)
            num += v1[3] * v2[3];
          if (v1[0] * v2[0] == ma)
            num += v1[1] * v2[1];
        } else {
          if (v1[0] * v2[0] == ma)
            num += v1[1] * v2[1];
          if (v1[0] * v2[2] == ma)
            num += v1[1] * v2[3];
          if (v1[2] * v2[0] == ma)
            num += v1[3] * v2[1];
          if (v1[2] * v2[2] == ma)
            num += v1[3] * v2[3];
        }
      }
      printf("%lld %lld\\n", ma, num);
    } else if (type == 3) {
      int mi = LLINF, num = 0;
      int a, b, c, d;
      scanf("%lld%lld%lld%lld", &a, &b, &c, &d);
      VI v1 = seg1.query(a - 1, b);
      VI v2 = seg2.query(c - 1, d);
      mi = min({v1[0] * v2[0], v1[2] * v2[2], v1[0] * v2[2], v1[2] * v2[0]});
      // minが0の場合
      if (mi == 0) {
        int tmpa = 0, tmpb = 0;
        if (v1[0] == 0)
          tmpa = v1[1];
        if (v1[2] == 0)
          tmpa = v1[3];
        if (v2[0] == 0)
          tmpb = v2[1];
        if (v2[2] == 0)
          tmpb = v2[3];
        num =
            (b - a + 1) * (d - c + 1) - (b - a + 1 - tmpa) * (d - c + 1 - tmpb);
      } else {
        if (v1[0] == v1[2] && v2[0] == v2[2]) {
          num = (b - a + 1) * (d - c + 1);
        } else if (v1[0] == v1[2] || v2[0] == v2[2]) {
          if (v1[2] * v2[2] == mi)
            num += v1[3] * v2[3];
          if (v1[0] * v2[0] == mi)
            num += v1[1] * v2[1];
        } else {
          if (v1[0] * v2[0] == mi)
            num += v1[1] * v2[1];
          if (v1[0] * v2[2] == mi)
            num += v1[1] * v2[3];
          if (v1[2] * v2[0] == mi)
            num += v1[3] * v2[1];
          if (v1[2] * v2[2] == mi)
            num += v1[3] * v2[3];
        }
      }
      printf("%lld %lld\\n", mi, num);
    }
    // seg1.debug();
    // seg2.debug();
  }

  return 0;
}