Problem:
E： たい焼きマスターと食べ盛り - Taiyaki-Master and Eater
物語
つたさんはたい焼きを作るのがとても上手い。えびちゃんはそんなつたさんが作るたい焼きが大好きだ。
2
人は毎週たい焼きを作って食べて幸せに過ごしているが、たい焼きを作っているそばで食べ盛りのえびちゃんにつまみ食いをされてしまうのがつたさんの最近の悩みだ。
学校祭でたい焼きを作ることになったつたさんは、いつものようにえびちゃんにつまみ食いされていたら売上が心配なので、自分が注目している範囲のたい焼きの様子を知ることができればいいなと思った。学校祭が成功するように、つたさんを助けてあげよう。
問題
縦
H
、横
W
の長方形状のたい焼きプレートがあり、たい焼きをセットしてから焼き上がるまでに
T
分かかる。このプレートはたい焼きを一度に最大
HW
個焼くことができ、プレートの上から
i
(1 \leq i \leq H)
番目で左から
j
(1 \leq j \leq W)
番目の場所で焼いているたい焼きは
(i, j)
で表される。
次の
3
種類のイベントが合計
Q
回発生する。なお、初期状態ではたい焼きはいずれの場所にもセットされていない。
時刻
t
につたさんが
(h, w)
にたい焼きを
1
つセットする。そのたい焼きは
T
分で焼き上がり、時刻
t+T
の時点で食べることができるようになる。ただし、すでにたい焼きがセットされている場所にたい焼きをセットすることはない。
時刻
t
に、えびちゃんが
(h, w)
にあるたい焼きをつまみ食いしようとする。ただし、
つまみ食いできるのはすでに焼き上がったたい焼きのみである
。つまみ食いした後はその場所からたい焼きが無くなる (すなわち、たい焼きがセットされていない状態になる)。たい焼きが焼き上がっていない、またはたい焼きがない場所にもつまみ食いのイベントが発生する場合があることに注意せよ。
左上が
(h_1, w_1)
、右下が
(h_2, w_2)
となるような長方形領域内 (
(h_1, w_1)
および
(h_2, w_2)
を含む) のたい焼きについて、次の数が時刻
t
の時点でそれぞれいくつであるかをつたさんがカウントする。
すでに焼き上がったたい焼きの数
まだ焼き上がっていないたい焼きの数
入力形式
H
W
T
Q
t_1
c_1
h_{11}
w_{11}
(h_{12}
w_{12})
t_2
c_2
h_{21}
w_{21}
(h_{22}
w_{22})
…
t_Q
c_Q
h_{Q1}
w_{Q1}
(h_{Q2}
w_{Q2})
入力は全て整数で与えられる。
1
行目には、たい焼きプレートの縦
H
、 横
W
、 たい焼きをセットしてから焼きあがるまでの時間
T
、 イベントの数
Q
が与えられる。
1+i
(1 \leq i \leq Q)
行目には、時刻
t_i
で発生したイベントの内容が与えられる。
c_i
はイベントの種類を表す。この値が
0
ならばたい焼きをセットするイベント、
1
ならばつまみ食いをするイベント、
2
ならばたい焼きをカウントするイベントを指す。
h_{i1}
(1 \leq h_{i1} \leq H)
、
w_{i1}
(1 \leq w_{i1} \leq W)
は、
c_i = 0, 1
において次のような意味である。
c_i = 0
のとき、
(h_{i1}, w_{i1})
の場所にたい焼きを1つセットする。
c_i = 1
のとき、
(h_{i1}, w_{i1})
の場所に焼き上がった状態のたい焼きがあればつまみ食いをし、そうでなければ何もしない。
h_{i2}
、
w_{i2}
は、
c_i = 2
のときのみ与えられる。
c_i = 2
のとき、左上を
(h_{i1}, w_{i1})
、 右下を
(h_{i2}, w_{i2})
とする長方形領域内のたい焼きについてカウントする。
入出力が非常に多くなることが予想されるため、入出力に遅い関数を使っている場合は注意してください。
制約
1 \leq H \leq 2 \times 10^3
1 \leq W \leq 2 \times 10^3
1 \leq T \leq 10^9
1 \leq Q \leq 10^5
1 \leq t_i \leq 10^9
i \lt j
ならば、
t_i \lt t_j
0 \leq c_i \leq 2
1 \leq h_{i1} \leq h_{i2} \leq H
1 \leq w_{i1} \leq w_{i2} \leq W
出力形式
(
c_i = 2
(1 \leq i \leq Q)
の個数) を
n
とする。たい焼きのカウントの結果を、次の書き方に従ってイベントの発生時間が早い順に
n
行に出力せよ。
a_1
b_1
a_2
b_2
…
a_n
b_n
a_i
は、領域内にある「焼き上がったたい焼きの数」である。
b_i
は、領域内にある「まだ焼き上がっていないたい焼きの数」である。
末尾の改行を忘れないこと。
入力例1
3 3 3 6
1 0 1 1
2 2 1 1 2 2
3 1 1 1
4 0 2 1
5 2 1 1 2 2
6 2 2 1 3 3
出力例1
0 1
1 1
0 1
この入出力例では以下のイベントが発生している。
時刻
1
分に、
(1, 1)
にたい焼きをセットする。このたい焼きは時刻
4
分に焼き上がる。
時刻
2
分に、左上
(1, 1)
、右下
(2, 2)
の長方形領域にあるたい焼きをカウントする。
(1, 1)
にセットしたたい焼きはまだ焼き上がっていないため、
0 1
を出力する。
時刻
3
分に、
(1, 1)
にあるたい焼きをつまみ食いしようとするが、まだ焼き上がっていないので何もしない。
時刻
4
分に、
(2, 1)
にたい焼きをセットする。このたい焼きは時刻
7
分に焼き上がる。
時刻
5
分に、左上
(1, 1)
、右下
(2, 2)
の長方形領域にあるたい焼きをカウントする。
(1, 1)
のたい焼きは焼き上がっており、
(2, 1)
のたい焼きはまだ焼き上がっていないため、
1 1
を出力する。
時刻
6
分に、左上
(2, 1)
、右下
(3, 3)
の長方形領域にあるたい焼きをカウントする。
(2, 1)
のたい焼きはまだ焼き上がっていないため、
0 1
を出力する。

Submitted solutions:

code_snippet: #include <iostream>
#include <stdio.h>
#include <string>
#include <stack>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <unordered_set>
#include <cmath>
#include <algorithm>
#include <bitset>
#include <climits>
#include <functional>
using namespace std;

template <typename T>
struct BIT {
    int h, w;
    vector<vector<T> > bit;
    BIT(int h_, int w_) : h(h_ + 1), w(w_ + 1), bit(h, vector<T>(w, 0)) {}
    void add(int r, int c, T x) {
        r++;
        c++;
        for (int ri = r; ri < h; ri += (ri & -ri)) {
            for (int ci = c; ci < w; ci += (ci & -ci)) {
                bit[ri][ci] += x;
            }
        }
    }
    T sum(int r, int c) {
        r++;
        c++;
        T s(0);

        for (int ri = r; ri > 0; ri -= (ri & -ri)) {
            for (int ci = c; ci > 0; ci -= (ci & -ci)) {
                s += bit[ri][ci];
            }
        }
        return s;
    }
    T sum(int r1, int c1, int r2, int c2) {
        return sum(r2, c2) - sum(r2, c1 - 1) - sum(r1 - 1, c2) + sum(r1 - 1, c1 - 1);
    }
};

int main() {
    int H, W, T, Q;
    cin >> H >> W >> T >> Q;

    vector<vector<bool> > v1(H, vector<bool>(W, false)), v2(H, vector<bool>(W, false));
    BIT<int> rsq1(H, W), rsq2(H, W);
    queue<tuple<int, int, int> > q;
    vector<pair<int, int> > ans;
    
    for (int i = 0; i < Q; i++) {
        int t, c, h1, w1, h2, w2;
        cin >> t >> c >> h1 >> w1;
        h1--;
        w1--;

        while (!q.empty() && get<2>(q.front()) <= t) {
            auto [r, c, _] = q.front();
            q.pop();
            rsq1.add(r, c, -1);
            rsq2.add(r, c, 1);
            v1[r][c] = false;
            v2[r][c] = true;
        }

        if (c == 0) {
            if (!v1[h1][w1] && !v2[h1][w1]) {
                v1[h1][w1] = true;
                rsq1.add(h1, w1, 1);
                q.push({h1, w1, t + T});
            }
        }
        else if (c == 1) {
            if (v2[h1][w1]) {
                rsq2.add(h1, w1, -1);
                v2[h1][w1] = false;
            }
        }
        else {
            cin >> h2 >> w2;
            h2--;
            w2--;

            int a = rsq2.sum(h1, w1, h2, w2);
            int b = rsq1.sum(h1, w1, h2, w2);

            ans.push_back({a, b});
        }

        // for (int r = 0; r < H; r++) {
        //     for (int c = 0; c < W; c++) {
        //         cout << v1[r][c] << " ";
        //     }
        //     cout << endl;
        // }
        // cout << "---" << endl;

        // for (int r = 0; r < H; r++) {
        //     for (int c = 0; c < W; c++) {
        //         cout << v2[r][c] << " ";
        //     }
        //     cout << endl;
        // }

        // cout << "=====" << endl;
        // cout << "=====" << endl;
    }

    for (auto [a, b]: ans) {
        cout << a << " " << b << endl;
    }
}
accuracy: 1
time_ms: 150
memory_kb: 37248
final_rank: 2

code_snippet: #ifndef HIDDEN_IN_VS // 折りたたみ用

// 警告の抑制
#define _CRT_SECURE_NO_WARNINGS

// ライブラリの読み込み
#include <bits/stdc++.h>
using namespace std;

// 型名の短縮
using ll = long long; using ull = unsigned long long; // -2^63 ～ 2^63 = 9e18（int は -2^31 ～ 2^31 = 2e9）
using pii = pair<int, int>;	using pll = pair<ll, ll>;	using pil = pair<int, ll>;	using pli = pair<ll, int>;
using vi = vector<int>;		using vvi = vector<vi>;		using vvvi = vector<vvi>;	using vvvvi = vector<vvvi>;
using vl = vector<ll>;		using vvl = vector<vl>;		using vvvl = vector<vvl>;	using vvvvl = vector<vvvl>;
using vb = vector<bool>;	using vvb = vector<vb>;		using vvvb = vector<vvb>;
using vc = vector<char>;	using vvc = vector<vc>;		using vvvc = vector<vvc>;
using vd = vector<double>;	using vvd = vector<vd>;		using vvvd = vector<vvd>;
template <class T> using priority_queue_rev = priority_queue<T, vector<T>, greater<T>>;
using Graph = vvi;

// 定数の定義
const double PI = acos(-1);
int DX[4] = { 1, 0, -1, 0 }; // 4 近傍（下，右，上，左）
int DY[4] = { 0, 1, 0, -1 };
int INF = 1001001001; ll INFL = 4004004003094073385LL; // (int)INFL = INF, (int)(-INFL) = -INF;

// 入出力高速化
struct fast_io { fast_io() { cin.tie(nullptr); ios::sync_with_stdio(false); cout << fixed << setprecision(18); } } fastIOtmp;

// 汎用マクロの定義
#define all(a) (a).begin(), (a).end()
#define sz(x) ((int)(x).size())
#define lbpos(a, x) (int)distance((a).begin(), std::lower_bound(all(a), (x)))
#define ubpos(a, x) (int)distance((a).begin(), std::upper_bound(all(a), (x)))
#define Yes(b) {cout << ((b) ? "Yes\n" : "No\n");}
#define rep(i, n) for(int i = 0, i##_len = int(n); i < i##_len; ++i) // 0 から n-1 まで昇順
#define repi(i, s, t) for(int i = int(s), i##_end = int(t); i <= i##_end; ++i) // s から t まで昇順
#define repir(i, s, t) for(int i = int(s), i##_end = int(t); i >= i##_end; --i) // s から t まで降順
#define repe(v, a) for(const auto& v : (a)) // a の全要素（変更不可能）
#define repea(v, a) for(auto& v : (a)) // a の全要素（変更可能）
#define repb(set, d) for(int set = 0, set##_ub = 1 << int(d); set < set##_ub; ++set) // d ビット全探索（昇順）
#define repis(i, set) for(int i = lsb(set), bset##i = set; i < 32; bset##i -= 1 << i, i = lsb(bset##i)) // set の全要素（昇順）
#define repp(a) sort(all(a)); for(bool a##_perm = true; a##_perm; a##_perm = next_permutation(all(a))) // a の順列全て（昇順）
#define uniq(a) {sort(all(a)); (a).erase(unique(all(a)), (a).end());} // 重複除去
#define EXIT(a) {cout << (a) << endl; exit(0);} // 強制終了
#define inQ(x, y, u, l, d, r) ((u) <= (x) && (l) <= (y) && (x) < (d) && (y) < (r)) // 半開矩形内判定

// 汎用関数の定義
template <class T> inline ll powi(T n, int k) { ll v = 1; rep(i, k) v *= n; return v; }
template <class T> inline bool chmax(T& M, const T& x) { if (M < x) { M = x; return true; } return false; } // 最大値を更新（更新されたら true を返す）
template <class T> inline bool chmin(T& m, const T& x) { if (m > x) { m = x; return true; } return false; } // 最小値を更新（更新されたら true を返す）
template <class T> inline T getb(T set, int i) { return (set >> i) & T(1); }
template <class T> inline T smod(T n, T m) { n %= m; if (n < 0) n += m; return n; } // 非負mod

// 演算子オーバーロード
template <class T, class U> inline istream& operator>>(istream& is, pair<T, U>& p) { is >> p.first >> p.second; return is; }
template <class T> inline istream& operator>>(istream& is, vector<T>& v) { repea(x, v) is >> x; return is; }
template <class T> inline vector<T>& operator--(vector<T>& v) { repea(x, v) --x; return v; }
template <class T> inline vector<T>& operator++(vector<T>& v) { repea(x, v) ++x; return v; }

#endif // 折りたたみ用


#if __has_include(<atcoder/all>)
#include <atcoder/all>
using namespace atcoder;

#ifdef _MSC_VER
#include "localACL.hpp"
#endif

using mint = modint998244353;
//using mint = static_modint<1000000007>;
//using mint = modint; // mint::set_mod(m);

namespace atcoder {
	inline istream& operator>>(istream& is, mint& x) { ll x_; is >> x_; x = x_; return is; }
	inline ostream& operator<<(ostream& os, const mint& x) { os << x.val(); return os; }
}
using vm = vector<mint>; using vvm = vector<vm>; using vvvm = vector<vvm>; using vvvvm = vector<vvvm>; using pim = pair<int, mint>;
#endif


#ifdef _MSC_VER // 手元環境（Visual Studio）
#include "local.hpp"
#else // 提出用（gcc）
inline int popcount(int n) { return __builtin_popcount(n); }
inline int popcount(ll n) { return __builtin_popcountll(n); }
inline int lsb(int n) { return n != 0 ? __builtin_ctz(n) : 32; }
inline int lsb(ll n) { return n != 0 ? __builtin_ctzll(n) : 64; }
inline int msb(int n) { return n != 0 ? (31 - __builtin_clz(n)) : -1; }
inline int msb(ll n) { return n != 0 ? (63 - __builtin_clzll(n)) : -1; }
#define dump(...)
#define dumpel(...)
#define dump_math(v)
#define input_from_file(f)
#define output_to_file(f)
#define Assert(b) { if (!(b)) { vc MLE(1<<30); EXIT(MLE.back()); } } // RE の代わりに MLE を出す
#endif


//【二次元フェニック木（アーベル群）】
/*
* Fenwick_tree_2D<S, op, o, inv>(int h, int w) : O(h w)
*	v[0..h)[0..w) = o() で初期化する．
*	要素はアーベル群 (S, op, o, inv) の元とする．
*
* Fenwick_tree_2D<S, op, o, inv>(vvS a) : O(h w)
*	v[0..h)[0..w) = a[0..h)[0..w) で初期化する．
*
* add(int x, int y, S val) : O(log h log w)
*	v[x][y] += val とする．
*
* set(int x, int y, S val) : O(log h log w)
*	v[x][y] = val とする．
*
* S get(int x, int y) : O(log h log w)
*	v[x][y] を返す．
*
* S sum(int x1, int x2, int y1, int y2) : O(log h log w)
*	∑v[x1..x2)[y1..y2) を返す．空なら o() を返す．
*/
template <class S, S(*op)(S, S), S(*o)(), S(*inv)(S)>
class Fenwick_tree_2D {
	// 参考 : https://algo-logic.info/binary-indexed-tree/

	// ノードの個数（要素数 + 1）
	int h, w;

	// v[x][y] : ∑[*..x][*..y] の値（x, y ： 1-indexed，v[0][*], v[*][0] は使わない）
	vector<vector<S>> v;

	// ∑v[1..x][1..y] を返す．空なら o() を返す．（x, y : 1-indexed）
	S sum_sub(int x, int y) const {
		S res = o();

		// 子に向かって累積 op() をとっていく．
		// i, j の最下位ビットから 1 を減算することで次の位置を得る．
		for (int i = x; i > 0; i -= i & -i) {
			for (int j = y; j > 0; j -= j & -j) {
				res = op(res, v[i][j]);
			}
		}

		return res;
	}

public:
	// v[0..h)[0..w) = o() で初期化する．
	Fenwick_tree_2D(int h_, int w_) : h(h_ + 1), w(w_ + 1), v(h, vector<S>(w, o())) {
		// verify : https://onlinejudge.u-aizu.ac.jp/problems/2842
	}

	// v[0..h)[0..w) = a[0..h)[0..w) で初期化する．
	Fenwick_tree_2D(const vector<vector<S>>& v_) : h(sz(v_) + 1), w(sz(v_[0]) + 1),
		v(h, vector<S>(w, o())) {
		// 配列の値を仮登録する．
		rep(i, h - 1) {
			rep(j, w - 1) {
				v[i + 1][j + 1] = v_[i][j];
			}
		}

		// 正しい値になるよう根に向かって累積和をとっていく．
		// j 方向
		repi(i, 1, h - 1) {
			for (int pow2 = 1; 2 * pow2 < w; pow2 *= 2) {
				for (int j = 2 * pow2; j < w; j += 2 * pow2) {
					v[i][j] = op(v[i][j], v[i][j - pow2]);
				}
			}
		}
		// i 方向
		repi(j, 1, w - 1) {
			for (int pow2 = 1; 2 * pow2 < h; pow2 *= 2) {
				for (int i = 2 * pow2; i < h; i += 2 * pow2) {
					v[i][j] = op(v[i][j], v[i - pow2][j]);
				}
			}
		}
	}
	Fenwick_tree_2D() {}

	// v[x][y] = val とする．（x, y : 0-indexed）
	void set(int x, int y, S val) {
		// 差分を求める．
		S d = op(val, inv(this->get(x, y)));

		add(x, y, d);
	}

	// v[x][y] を返す．（x, y : 0-indexed）
	S get(int x, int y) const {
		return sum(x, x + 1, y, y + 1);
	}

	// ∑v[x1..x2)[y1..y2) を返す．空なら o() を返す．（x1, y1, x2, y2 : 0-indexed）
	S sum(int x1, int x2, int y1, int y2) const {
		// verify : https://onlinejudge.u-aizu.ac.jp/problems/2842

		// 0-indexed での半開長方形 [x1..x2) * [y1..y2) は，
		// 1-indexed での閉長方形 [x1+1..x2] * [y1+1..y2] に対応する．
		S res = o();
		res = op(res, sum_sub(x2, y2));
		res = op(res, inv(sum_sub(x2, y1)));
		res = op(res, inv(sum_sub(x1, y2)));
		res = op(res, sum_sub(x1, y1));
		return res;
	}

	// v[x][y] += val とする．（x, y : 0-indexed）
	void add(int x, int y, S val) {
		// verify : https://onlinejudge.u-aizu.ac.jp/problems/2842

		// x, y を 1-indexed に直す．
		x++; y++;

		// 根に向かって値を加算していく．
		// i, j の最下位ビットに 1 を加算することで次の位置を得る．
		for (int i = x; i < h; i += i & -i) {
			for (int j = y; j < w; j += j & -j) {
				v[i][j] = op(v[i][j], val);
			}
		}
	}

#ifdef _MSC_VER
	friend ostream& operator<<(ostream& os, const Fenwick_tree_2D& ft) {
		rep(x, ft.h - 1) {
			rep(y, ft.w - 1) {
				os << ft.get(x, y) << " ";
			}
			cout << "\n";
		}
		return os;
	}
#endif
};



//【総和 アーベル群】
/* verify : https://judge.yosupo.jp/problem/point_add_range_sum */
using S601 = ll;
S601 op601(S601 a, S601 b) { return a + b; }
S601 e601() { return 0; }
S601 inv601(S601 a) { return -a; }
#define Sum_group S601, op601, e601, inv601


int main() {
//	input_from_file("input.txt");
//	output_to_file("output.txt");

	int h, w, T, q;
	cin >> h >> w >> T >> q;

	// 焼き上がった／焼き上がっていないたい焼きの有無を記憶する二次元フェニック木
	Fenwick_tree_2D<Sum_group> ft_ok(h, w);
	Fenwick_tree_2D<Sum_group> ft_ng(h, w);

	// たい焼きがいつ焼き上がるかを記憶するキュー
	// (x, y, t) で位置 (x, y) のたい焼きが時刻 t に焼き上がることを意味する．
	queue<tuple<int, int, int>> que;

	rep(i, q) {
		int t, c;
		cin >> t >> c;

		// 焼き上がりが早い順に que 内のたい焼きを処理する．
		while (!que.empty()) {
			auto [x, y, t1] = que.front();

			// たい焼きがまだ焼き上がっていないなら ft_ok に追加しない．
			if (t1 > t) {
				break;
			}

			// 焼き上がったたい焼きは que から消して ft_ok に追加，ft_ng から削除する．
			que.pop();
			ft_ok.add(x, y, 1);
			ft_ng.add(x, y, -1);
		}

		// たい焼きのセット
		if (c == 0) {
			int h1, w1;
			cin >> h1 >> w1;
			h1--;
			w1--;

			// ft_ng に焼き上がっていないたい焼きを追加する．
			ft_ng.add(h1, w1, 1);

			// 今の時刻 t の T 時間後にたい焼きが焼き上がることを que に記憶する．
			que.push({ h1, w1, t + T });
		}
		// つまみ食い
		else if (c == 1) {
			int h1, w1;
			cin >> h1 >> w1;
			h1--;
			w1--;

			// 焼き上がったたい焼きがあればつまみ食いする．
			if (ft_ok.get(h1, w1) == 1) {
				ft_ok.add(h1, w1, -1);
			}
		}
		// カウント
		else {
			int h1, w1, h2, w2;
			cin >> h1 >> w1 >> h2 >> w2;
			h1--;
			w1--;

			cout << ft_ok.sum(h1, h2, w1, w2) << " ";
			cout << ft_ng.sum(h1, h2, w1, w2) << endl;
		}
	}
}
accuracy: 1
time_ms: 180
memory_kb: 66780
final_rank: 11

code_snippet: #ifndef HIDDEN_IN_VISUAL_STUDIO // 折りたたみ用

// 警告の抑制
#define _CRT_SECURE_NO_WARNINGS

// ライブラリの読み込み
#include <bits/stdc++.h>
using namespace std;

// 型名の短縮
using ll = long long; // -2^63 ～ 2^63 = 9 * 10^18（int は -2^31 ～ 2^31 = 2 * 10^9）
using pii = pair<int, int>;	using pll = pair<ll, ll>;	using pil = pair<int, ll>;	using pli = pair<ll, int>;
using vi = vector<int>;		using vvi = vector<vi>;		using vvvi = vector<vvi>;
using vl = vector<ll>;		using vvl = vector<vl>;		using vvvl = vector<vvl>;
using vb = vector<bool>;	using vvb = vector<vb>;		using vvvb = vector<vvb>;
using vc = vector<char>;	using vvc = vector<vc>;		using vvvc = vector<vvc>;
using vd = vector<double>;	using vvd = vector<vd>;		using vvvd = vector<vvd>;
template <class T> using priority_queue_rev = priority_queue<T, vector<T>, greater<T>>;
using Graph = vvi;

// 定数の定義
const double PI = 3.1415926535897932384626433832795;
const double DEG = PI / 180.; // θ [deg] = θ * DEG [rad]
const vi dx4 = { 1, 0, -1, 0 }; // 4 近傍（下，右，上，左）
const vi dy4 = { 0, 1, 0, -1 };
const vi dx8 = { 1, 1, 0, -1, -1, -1, 0, 1 }; // 8 近傍
const vi dy8 = { 0, 1, 1, 1, 0, -1, -1, -1 };
const int INF = 1001001001; const ll INFL = 2002002002002002002LL;
const double EPS = 1e-10; // 許容誤差に応じて調整

// 入出力高速化
struct fast_io { fast_io() { cin.tie(nullptr); ios::sync_with_stdio(false); cout << fixed << setprecision(15); } } fastIOtmp;

// 汎用マクロの定義
#define all(a) (a).begin(), (a).end()
#define sz(x) ((int)(x).size())
#define distance (int)distance
#define Yes(b) {cout << ((b) ? "Yes" : "No") << endl;}
#define rep(i, n) for(int i = 0, i##_len = int(n); i < i##_len; ++i) // 0 から n-1 まで昇順
#define repi(i, s, t) for(int i = int(s), i##_end = int(t); i <= i##_end; ++i) // s から t まで昇順
#define repir(i, s, t) for(int i = int(s), i##_end = int(t); i >= i##_end; --i) // s から t まで降順
#define repe(v, a) for(const auto& v : (a)) // a の全要素（変更不可能）
#define repea(v, a) for(auto& v : (a)) // a の全要素（変更可能）
#define repb(set, d) for(int set = 0; set < (1 << int(d)); ++set) // d ビット全探索（昇順）
#define repp(a) sort(all(a)); for(bool a##_perm = true; a##_perm; a##_perm = next_permutation(all(a))) // a の順列全て（昇順）
#define repit(it, a) for(auto it = (a).begin(); it != (a).end(); ++it) // イテレータを回す（昇順）
#define repitr(it, a) for(auto it = (a).rbegin(); it != (a).rend(); ++it) // イテレータを回す（降順）
#define smod(n, m) ((((n) % (m)) + (m)) % (m)) // 非負mod
#define uniq(a) {sort(all(a)); (a).erase(unique(all(a)), (a).end());} // 重複除去

// 汎用関数の定義
template <class T> inline ll pow(T n, int k) { ll v = 1; rep(i, k) v *= n; return v; }
template <class T> inline bool chmax(T& M, const T& x) { if (M < x) { M = x; return true; } return false; } // 最大値を更新（更新されたら true を返す）
template <class T> inline bool chmin(T& m, const T& x) { if (m > x) { m = x; return true; } return false; } // 最小値を更新（更新されたら true を返す）

// 演算子オーバーロード
template <class T, class U> inline istream& operator>> (istream& is, pair<T, U>& p) { is >> p.first >> p.second; return is; }
template <class T, class U> inline ostream& operator<< (ostream& os, const pair<T, U>& p) { os << "(" << p.first << "," << p.second << ")"; return os; }
template <class T, class U, class V> inline istream& operator>> (istream& is, tuple<T, U, V>& t) { is >> get<0>(t) >> get<1>(t) >> get<2>(t); return is; }
template <class T, class U, class V> inline ostream& operator<< (ostream& os, const tuple<T, U, V>& t) { os << "(" << get<0>(t) << "," << get<1>(t) << "," << get<2>(t) << ")"; return os; }
template <class T, class U, class V, class W> inline istream& operator>> (istream& is, tuple<T, U, V, W>& t) { is >> get<0>(t) >> get<1>(t) >> get<2>(t) >> get<3>(t); return is; }
template <class T, class U, class V, class W> inline ostream& operator<< (ostream& os, const tuple<T, U, V, W>& t) { os << "(" << get<0>(t) << "," << get<1>(t) << "," << get<2>(t) << "," << get<3>(t) << ")"; return os; }
template <class T> inline istream& operator>> (istream& is, vector<T>& v) { repea(x, v) is >> x; return is; }
template <class T> inline ostream& operator<< (ostream& os, const vector<T>& v) { repe(x, v) os << x << " "; return os; }
template <class T> inline ostream& operator<< (ostream& os, const list<T>& v) { repe(x, v) os << x << " "; return os; }
template <class T> inline ostream& operator<< (ostream& os, const set<T>& s) { repe(x, s) os << x << " "; return os; }
template <class T> inline ostream& operator<< (ostream& os, const set<T, greater<T>>& s) { repe(x, s) os << x << " "; return os; }
template <class T> inline ostream& operator<< (ostream& os, const unordered_set<T>& s) { repe(x, s) os << x << " "; return os; }
template <class T, class U> inline ostream& operator<< (ostream& os, const map<T, U>& m) { repe(p, m) os << p << " "; return os; }
template <class T, class U> inline ostream& operator<< (ostream& os, const unordered_map<T, U>& m) { repe(p, m) os << p << " "; return os; }
template <class T> inline ostream& operator<< (ostream& os, stack<T> s) { while (!s.empty()) { os << s.top() << " "; s.pop(); } return os; }
template <class T> inline ostream& operator<< (ostream& os, queue<T> q) { while (!q.empty()) { os << q.front() << " "; q.pop(); } return os; }
template <class T> inline ostream& operator<< (ostream& os, deque<T> q) { while (!q.empty()) { os << q.front() << " "; q.pop_front(); } return os; }
template <class T> inline ostream& operator<< (ostream& os, priority_queue<T> q) { while (!q.empty()) { os << q.top() << " "; q.pop(); } return os; }
template <class T> inline ostream& operator<< (ostream& os, priority_queue_rev<T> q) { while (!q.empty()) { os << q.top() << " "; q.pop(); } return os; }
template <class T> inline vector<T>& operator--(vector<T>& v) { rep(_i_, sz(v)) --v[_i_]; return v; }
template <class T> inline vector<T>& operator++(vector<T>& v) { rep(_i_, sz(v)) ++v[_i_]; return v; }

// 手元環境（Visual Studio）
#ifdef _MSC_VER
#define popcount (int)__popcnt // 全ビット中の 1 の個数
#define popcountll (int)__popcnt64
inline int lsb(unsigned int n) { unsigned long i; _BitScanForward(&i, n); return i; } // 最下位ビットの位置（0-indexed）
inline int lsbll(unsigned long long n) { unsigned long i; _BitScanForward64(&i, n); return i; }
inline int msb(unsigned int n) { unsigned long i; _BitScanReverse(&i, n); return i; } // 最上位ビットの位置（0-indexed）
inline int msbll(unsigned long long n) { unsigned long i; _BitScanReverse64(&i, n); return i; }
template <class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }
#define dump(x) cout << "\033[1;36m" << (x) << "\033[0m" << endl;
#define dumps(x) cout << "\033[1;36m" << (x) << "\033[0m ";
#define dumpel(a) { int _i_ = -1; cout << "\033[1;36m"; repe(x, a) {cout << ++_i_ << ": " << x << endl;} cout << "\033[0m"; }
#define input_from_file(f) ifstream isTMP(f); cin.rdbuf(isTMP.rdbuf());
#define output_to_file(f) ofstream osTMP(f); cout.rdbuf(osTMP.rdbuf());
// 提出用（gcc）
#else
#define popcount (int)__builtin_popcount
#define popcountll (int)__builtin_popcountll
#define lsb __builtin_ctz
#define lsbll __builtin_ctzll
#define msb(n) (31 - __builtin_clz(n))
#define msbll(n) (63 - __builtin_clzll(n))
#define gcd __gcd
#define dump(x)
#define dumps(x)
#define dumpel(v)
#define input_from_file(f)
#define output_to_file(f)
#endif

#endif // 折りたたみ用


////-----------------AtCoder 専用-----------------
//#include <atcoder/all>
//using namespace atcoder;
//
//using mint = modint1000000007;
////using mint = modint998244353;
////using mint = modint; // mint::set_mod(m);
//
//istream& operator>> (istream& is, mint& x) { ll x_; is >> x_; x = x_; return is; }
//ostream& operator<< (ostream& os, const mint& x) { os << x.val(); return os; }
//using vm = vector<mint>;	using vvm = vector<vm>;		using vvvm = vector<vvm>;
//
//template <class S, S(*op)(S, S), S(*e)()>ostream& operator<<(ostream& os, segtree<S, op, e> seg) { int n = seg.max_right(0, [](S x) {return true; }); rep(i, n) os << seg.get(i) << " "; return os; }
//template <class S, S(*op)(S, S), S(*e)(), class F, S(*mp)(F, S), F(*cp)(F, F), F(*id)()>ostream& operator<<(ostream& os, lazy_segtree<S, op, e, F, mp, cp, id> seg) { int n = seg.max_right(0, [](S x) {return true; }); rep(i, n) os << seg.get(i) << " "; return os; }
//ostream& operator<<(ostream& os, dsu d) { repe(g, d.groups()) { repe(v, g) { os << v << " "; } os << endl; } return os; };
////----------------------------------------------


//【二次元フェニック木（アーベル群）】
/*
* Fenwick_tree_2D<S, op, e, inv>(int h, int w) : O(h w)
*	要素数 h * w かつ初期値 e で初期化する．
*	要素はアーベル群 (S, op, e, inv) の元とする．
*
* Fenwick_tree_2D<S, op, e, inv>(vvS a) : O(h w)
*	二次元配列 a で初期化する．
*
* apply(int x, int y, S val) : O(log h log w)
*	v[x][y] = op(v[x][y], val) とする．
*
* set(int x, int y, S val) : O(log h log w)
*	v[x][y] = val とする．
*
* S get(int x, int y) : O(log h log w)
*	v[x][y] を返す．
*
* S prod(int x1, int y1, int x2, int y2) : O(log h log w)
*	op( v[x1..x2)[y1..y2) ) を返す．空なら e() を返す．
*/
template <class S, S(*op)(S, S), S(*e)(), S(*inv)(S)>
struct Fenwick_tree_2D {
	// 参考：https://algo-logic.info/binary-indexed-tree/

	// ノードの個数（要素数 + 1）
	int h, w;

	// v[x][y] : op( [*..x][*..y] ) の値（x, y ： 1-indexed，v[0][*], v[*][0] は使わない）
	vector<vector<S>> v;

	// コンストラクタ（初期化なし）
	Fenwick_tree_2D() {}

	// 要素数 h * w かつ初期値 e で初期化
	Fenwick_tree_2D(int h_, int w_) : h(h_ + 1), w(w_ + 1), v(h, vector<S>(w, e())) {}

	// 配列 a で初期化
	Fenwick_tree_2D(const vector<vector<S>>& v_) : h(sz(v_) + 1), w(sz(v_[0]) + 1),
		v(h, vector<S>(w, e())) {
		// 配列の値を仮登録する．
		rep(i, h - 1) {
			rep(j, w - 1) {
				v[i + 1][j + 1] = v_[i][j];
			}
		}

		// 正しい値になるよう根に向かって累積 op() をとっていく．
		// j 方向
		repi(i, 1, h - 1) {
			for (int pow2 = 1; 2 * pow2 < w; pow2 *= 2) {
				for (int j = 2 * pow2; j < w; j += 2 * pow2) {
					v[i][j] = op(v[i][j], v[i][j - pow2]);
				}
			}
		}
		// i 方向
		repi(j, 1, w - 1) {
			for (int pow2 = 1; 2 * pow2 < h; pow2 *= 2) {
				for (int i = 2 * pow2; i < h; i += 2 * pow2) {
					v[i][j] = op(v[i][j], v[i - pow2][j]);
				}
			}
		}
	}

	// v[x][y] = val とする．（x, y : 0-indexed）
	void set(int x, int y, S val) {
		// 差分を求める．
		S d = op(val, inv(get(x, y)));

		apply(x, y, d);
	}

	// v[x][y] を返す．（x, y : 0-indexed）
	S get(int x, int y) const {
		return prod(x, y, x + 1, y + 1);
	}

	// op( v[x1..x2)[y1..y2) ) を返す．空なら e を返す．（x1, y1, x2, y2 : 0-indexed）
	S prod(int x1, int y1, int x2, int y2) const {
		// 0-indexed での半開長方形 [x1..x2) * [y1..y2) は，
		// 1-indexed での閉長方形 [x1+1..x2] * [y1+1..y2] に対応する．
		S res = e();
		res = op(res, prod_sub(x2, y2));
		res = op(res, inv(prod_sub(x2, y1)));
		res = op(res, inv(prod_sub(x1, y2)));
		res = op(res, prod_sub(x1, y1));
		return res;
	}

	// op( v[1..x][1..y] ) を返す．空なら e を返す．（x, y : 1-indexed）
	S prod_sub(int x, int y) const {
		S res = e();

		// 子に向かって累積 op() をとっていく．
		// i, j の最下位ビットから 1 を減算することで次の位置を得る．
		for (int i = x; i > 0; i -= i & -i) {
			for (int j = y; j > 0; j -= j & -j) {
				res = op(res, v[i][j]);
			}
		}

		return res;
	}

	// v[x][y] = op(v[x][y], val) とする．（x, y : 0-indexed）
	void apply(int x, int y, S val) {
		// x, y を 1-indexed に直す．
		x++; y++;

		// 根に向かって値を op() していく．
		// i, j の最下位ビットに 1 を加算することで次の位置を得る．
		for (int i = x; i < h; i += i & -i) {
			for (int j = y; j < w; j += j & -j) {
				v[i][j] = op(v[i][j], val);
			}
		}
	}

	// デバッグ出力用
	friend ostream& operator<<(ostream& os, const Fenwick_tree_2D& ft) {
		rep(x, ft.h - 1) {
			rep(y, ft.w - 1) {
				os << ft.get(x, y) << " ";
			}
			cout << "\n";
		}
		return os;
	}
};


//【加算 アーベル群】
using S201 = ll;
S201 op201(S201 a, S201 b) { return a + b; }
S201 o201() { return 0; }
S201 inv201(S201 a) { return -a; }
#define Add_abel_group S201, op201, o201, inv201


int main() {
//	input_from_file("input.txt");
//	output_to_file("output.txt");

	int h, w, T, q;
	cin >> h >> w >> T >> q;

	// 焼き上がった／焼き上がっていないたい焼きの有無を記憶する二次元フェニック木
	Fenwick_tree_2D<Add_abel_group> ft_ok(h, w);
	Fenwick_tree_2D<Add_abel_group> ft_ng(h, w);

	// たい焼きがいつ焼き上がるかを記憶するキュー
	// (x, y, t) で位置 (x, y) のたい焼きが時刻 t に焼き上がることを意味する．
	queue<tuple<int, int, int>> que;

	rep(i, q) {
		int t, c;
		cin >> t >> c;

		// 焼き上がりが早い順に que 内のたい焼きを処理する．
		while (!que.empty()) {
			int x, y, t1;
			tie(x, y, t1) = que.front();

			// たい焼きがまだ焼き上がっていないなら ft_ok に追加しない．
			if (t1 > t) {
				break;
			}

			// 焼き上がったたい焼きは que から消して ft_ok に追加，ft_ng から削除する．
			que.pop();
			ft_ok.apply(x, y, 1);
			ft_ng.apply(x, y, -1);
		}

		// たい焼きのセット
		if (c == 0) {
			int h1, w1;
			cin >> h1 >> w1;
			h1--;
			w1--;

			// ft_ng に焼き上がっていないたい焼きを追加する．
			ft_ng.apply(h1, w1, 1);

			// 今の時刻 t の T 時間後にたい焼きが焼き上がることを que に記憶する．
			que.push({ h1, w1, t + T });
		}
		// つまみ食い
		else if (c == 1) {
			int h1, w1;
			cin >> h1 >> w1;
			h1--;
			w1--;

			// 焼き上がったたい焼きがあればつまみ食いする．
			if (ft_ok.get(h1, w1) == 1) {
				ft_ok.apply(h1, w1, -1);
			}
		}
		// カウント
		else {
			int h1, w1, h2, w2;
			cin >> h1 >> w1 >> h2 >> w2;
			h1--;
			w1--;

			cout << ft_ok.prod(h1, w1, h2, w2) << " ";
			cout << ft_ng.prod(h1, w1, h2, w2) << endl;
		}
	}
}
accuracy: 1
time_ms: 180
memory_kb: 66784
final_rank: 12

code_snippet: #include <bits/stdc++.h>
using namespace std;
random_device seed_gen;
mt19937 rnd(seed_gen());

using ll = long long;
using ull = unsigned long long;
using vi = vector<int>;
using vvi = vector<vi>;
using vvvi = vector<vvi>;
using vl = vector<ll>;
using vvl = vector<vl>;
using vvvl = vector<vvl>;
using Pii = pair<int, int>;
using Pll = pair<ll, ll>;
using Pil = pair<int, ll>;
using Pli = pair<ll, int>;
template <typename T>
inline bool chmax(T &a, T b) {
    return ((a < b) ? (a = b, true) : (false));
}
template <typename T>
inline bool chmin(T &a, T b) {
    return ((a > b) ? (a = b, true) : (false));
}
bool eq(double a, double b) { return abs(a - b) < 0.0000001; }
const string LRUD = "LRUD";
const int di4[4] = {0, 0, -1, 1}, dj4[4] = {-1, 1, 0, 0};
const int di8[8] = {0, 0, 1, 1, 1, -1, -1, -1},
          dj8[8] = {1, -1, 0, -1, 1, 0, -1, 1};

#define rep(i, n) for (int i = 0; i < n; i++)
#define rep1(i, n) for (int i = 1; i <= n; i++)
#define Rrep(i, n) for (int i = n - 1; i >= 0; i--)
#define Rrep1(i, n) for (int i = n; i > 0; i--)
#define all(a) a.begin(), a.end()
#define sz(a) ssize(a)
#define yesno(ans) cout << ((ans) ? "Yes\n" : "No\n")
#define YESNO(ans) cout << ((ans) ? "YES\n" : "NO\n")
#define INF ((ll)2e18)
#define IINF ((int)(1e9 + 5e8))
const double PI = 3.1415926535897932384626;
#define eb emplace_back
#define pb push_back

template <typename CharT, typename Traits, class T>
basic_ostream<CharT, Traits> &operator<<(basic_ostream<CharT, Traits> &os,
                                         const vector<T> &vec) {
    bool f = false;
    for (auto x : vec) {
        if (f)
            os << ",";
        f = true;
        os << x;
    }
    return os;
}
#ifdef _LOCAL
#define dbg(x) cerr << __LINE__ << "行:" << #x << "={" << (x) << "}" << endl;
#else
#define dbg(x) true
#endif

/*
#include <atcoder/modint>
using namespace atcoder;
// using mint=modint;
using mint = modint998244353;
// using mint = modint1000000007;
using vm = vector<mint>;
using vvm = vector<vm>;
using vvvm = vector<vvm>;
//*/

template <class T>
struct fenwick_tree2D {
public:
    fenwick_tree2D() : _h(0), _w(0) {}
    explicit fenwick_tree2D(int h, int w) : _h(h + 1), _w(w + 1), data(h + 1, vector<T>(w + 1, 0)) {}

    void add(int r, int c, T x) {
        r++, c++; // 1-originに変換
        for (int i = r; i < _h; i += (i & -i)) {
            for (int j = c; j < _w; j += (j & -j)) {
                data[i][j] += x;
            }
        }
    }

    T sum(int r, int c) {
        T ret = 0;
        // r++, c++; // 1-originに変換 r++,c++
        // r--, c--; // 開区間に変換 r--,c-- ->あわせるとかわらない
        for (int i = r; i > 0; i -= (i & -i)) {
            for (int j = c; j > 0; j -= (j & -j)) {
                ret += data[i][j];
            }
        }
        return ret;
    }

    T sum(int r1, int c1, int r2, int c2) {
        return +sum(r2, c2) + sum(r1, c1) - sum(r1, c2) - sum(r2, c1);
    }

private:
    int _h, _w;
    vector<vector<T>> data;
};

void solve() {
    int H, W, T, Q;
    cin >> H >> W >> T >> Q;
    fenwick_tree2D<int> ft0(H + 11, W + 11); // すでに焼きあがったたい焼き
    fenwick_tree2D<int> ft1(H + 11, W + 11); // まだ焼きあがっていないたい焼き
    vvi memo(H, vi(W, -1));
    using Pair = pair<int, Pii>; // 時間と座標
    priority_queue<Pair, vector<Pair>, greater<Pair>> q;
    while (Q--) {
        int t, c;
        cin >> t >> c;
        // たい焼きの焼き上がりを見る
        while (!q.empty()) {
            int tt = q.top().first;
            auto [r, c] = q.top().second;
            if (t - tt < T)
                break;
            if (memo[r][c] != -1) {
                // 焼きあがっているかつたい焼きがある
                ft1.add(r, c, -1);
                ft0.add(r, c, 1);
            }
            q.pop();
        }

        if (c == 0) {
            int h, w;
            cin >> h >> w;
            h--, w--;
            memo[h][w] = t;
            ft1.add(h, w, 1);
            q.push(Pair(t, Pii(h, w)));
        } else if (c == 1) {
            int h, w;
            cin >> h >> w;
            h--, w--;
            if (ft0.sum(h, w, h + 1, w + 1) == 1) {
                ft0.add(h, w, -1);
                memo[h][w] = -1;
            }
        } else if (c == 2) {
            int h1, w1, h2, w2;
            cin >> h1 >> w1 >> h2 >> w2;
            h1--, w1--;
            cout << ft0.sum(h1, w1, h2, w2) << " " << ft1.sum(h1, w1, h2, w2) << endl;
        }
    }
}

int main() {
    int T = 1;
    // cin>>T;
    while (T--) {
        solve();
    }
    return 0;
}
accuracy: 1
time_ms: 220
memory_kb: 52288
final_rank: 14

code_snippet: #include <bits/stdc++.h>
using namespace std;
random_device seed_gen;
mt19937 rnd(seed_gen());

using ll = long long;
using ull = unsigned long long;
using vi = vector<int>;
using vvi = vector<vi>;
using vvvi = vector<vvi>;
using vl = vector<ll>;
using vvl = vector<vl>;
using vvvl = vector<vvl>;
using Pii = pair<int, int>;
using Pll = pair<ll, ll>;
using Pil = pair<int, ll>;
using Pli = pair<ll, int>;
template <typename T>
inline bool chmax(T &a, T b) {
    return ((a < b) ? (a = b, true) : (false));
}
template <typename T>
inline bool chmin(T &a, T b) {
    return ((a > b) ? (a = b, true) : (false));
}
bool eq(double a, double b) { return abs(a - b) < 0.0000001; }
const string LRUD = "LRUD";
const int di4[4] = {0, 0, -1, 1}, dj4[4] = {-1, 1, 0, 0};
const int di8[8] = {0, 0, 1, 1, 1, -1, -1, -1},
          dj8[8] = {1, -1, 0, -1, 1, 0, -1, 1};

#define rep(i, n) for (int i = 0; i < n; i++)
#define rep1(i, n) for (int i = 1; i <= n; i++)
#define Rrep(i, n) for (int i = n - 1; i >= 0; i--)
#define Rrep1(i, n) for (int i = n; i > 0; i--)
#define all(a) a.begin(), a.end()
#define sz(a) ssize(a)
#define yesno(ans) cout << ((ans) ? "Yes\n" : "No\n")
#define YESNO(ans) cout << ((ans) ? "YES\n" : "NO\n")
#define INF ((ll)2e18)
#define IINF ((int)(1e9 + 5e8))
const double PI = 3.1415926535897932384626;
#define eb emplace_back
#define pb push_back

template <typename CharT, typename Traits, class T>
basic_ostream<CharT, Traits> &operator<<(basic_ostream<CharT, Traits> &os,
                                         const vector<T> &vec) {
    bool f = false;
    for (auto x : vec) {
        if (f)
            os << ",";
        f = true;
        os << x;
    }
    return os;
}
#ifdef _LOCAL
#define dbg(x) cerr << __LINE__ << "行:" << #x << "={" << (x) << "}" << endl;
#else
#define dbg(x) true
#endif

/*
#include <atcoder/modint>
using namespace atcoder;
// using mint=modint;
using mint = modint998244353;
// using mint = modint1000000007;
using vm = vector<mint>;
using vvm = vector<vm>;
using vvvm = vector<vvm>;
//*/

template <class T>
struct fenwick_tree2D {
public:
    fenwick_tree2D() : _h(0), _w(0) {}
    explicit fenwick_tree2D(int h, int w) : _h(h + 1), _w(w + 1), data(h + 1, vector<T>(w + 1, 0)) {}

    void add(int r, int c, T x) {
        r++, c++; // 1-originに変換
        for (int i = r; i < _h; i += (i & -i)) {
            for (int j = c; j < _w; j += (j & -j)) {
                data[i][j] += x;
            }
        }
    }

    T sum(int r, int c) {
        T ret = 0;
        r++, c++; // 1-originに変換
        r--, c--; // 開区間に変換
        for (int i = r; i > 0; i -= (i & -i)) {
            for (int j = c; j > 0; j -= (j & -j)) {
                ret += data[i][j];
            }
        }
        return ret;
    }

    T sum(int r1, int c1, int r2, int c2) {
        return +sum(r2, c2) + sum(r1, c1) - sum(r1, c2) - sum(r2, c1);
    }

private:
    int _h, _w;
    vector<vector<T>> data;
};

void solve() {
    int H, W, T, Q;
    cin >> H >> W >> T >> Q;
    fenwick_tree2D<int> ft0(H + 11, W + 11); // すでに焼きあがったたい焼き
    fenwick_tree2D<int> ft1(H + 11, W + 11); // まだ焼きあがっていないたい焼き
    vvi memo(H, vi(W, -1));
    using Pair = pair<int, Pii>; // 時間と座標
    priority_queue<Pair, vector<Pair>, greater<Pair>> q;
    while (Q--) {
        int t, c;
        cin >> t >> c;
        // たい焼きの焼き上がりを見る
        while (!q.empty()) {
            int tt = q.top().first;
            auto [r, c] = q.top().second;
            if (t - tt < T)
                break;
            if (memo[r][c] != -1) {
                // 焼きあがっているかつたい焼きがある
                ft1.add(r, c, -1);
                ft0.add(r, c, 1);
            }
            q.pop();
        }

        if (c == 0) {
            int h, w;
            cin >> h >> w;
            h--, w--;
            memo[h][w] = t;
            ft1.add(h, w, 1);
            q.push(Pair(t, Pii(h, w)));
        } else if (c == 1) {
            int h, w;
            cin >> h >> w;
            h--, w--;
            if (ft0.sum(h, w, h + 1, w + 1) == 1) {
                ft0.add(h, w, -1);
                memo[h][w] = -1;
            }
        } else if (c == 2) {
            int h1, w1, h2, w2;
            cin >> h1 >> w1 >> h2 >> w2;
            h1--, w1--;
            cout << ft0.sum(h1, w1, h2, w2) << " " << ft1.sum(h1, w1, h2, w2) << endl;
        }
    }
}

int main() {
    int T = 1;
    // cin>>T;
    while (T--) {
        solve();
    }
    return 0;
}
accuracy: 1
time_ms: 220
memory_kb: 52148
final_rank: 13

code_snippet: #include <bits/stdc++.h>

using namespace std;

template <typename T>
class fenwick_tree_2d {
  int r, c;
  vector<vector<T>> a;

public:
  fenwick_tree_2d(int r, int c): r(r), c(c), a(r+1, vector<T>(c+1)) {}

  // return the sum of a[i][j] for 1 <= i <= y and 1 <= j <= x.
  T sum(int y, int x) {
    T s = 0;
    for (int i = y; i > 0; i -= i & -i) {
      for (int j = x; j > 0; j -= j & -j) {
	s += a[i][j];
      }
    }
    return s;
  }

  // return the sum of a[i][j] for y1 <= i <= y2 and x1 <= j <= x2.
  T sum(int y1, int x1, int y2, int x2) {
    return sum(y2, x2) - sum(y1-1, x2) - sum(y2, x1-1) + sum(y1-1, x1-1);
  }

  // add v to a[y][x], where y in [1, r] and x in [1, c].
  void add(int y, int x, T val) {
    for (int i = y; i <= r; i += i & -i) {
      for (int j = x; j <= c; j += j & -j) {
	a[i][j] += val;
      }
    }
  }
};

void solve() {
  int H, W, T, Q;
  cin >> H >> W >> T >> Q;

  vector<tuple<int, int, int, int, int, int>> evt;
  for (int i = 0; i < Q; i++) {
    int t, c, h1, w1, h2, w2;
    cin >> t >> c >> h1 >> w1;
    if (c == 2)
      cin >> h2 >> w2;
    evt.emplace_back(t, c, h1, w1, h2, w2);
    if (c == 0)
      evt.emplace_back(t + T, -1,  h1, w1, h2, w2);
  }

  sort(evt.begin(), evt.end());

  fenwick_tree_2d<int> tree1(H, W), tree2(H, W);
  for (auto &[t, c, h1, w1, h2, w2]: evt) {
    if (c == -1) {
      tree1.add(h1, w1, -1);
      tree2.add(h1, w1, 1);
    } else if (c == 0) {
      tree1.add(h1, w1, 1);
    } else if (c == 1) {
      if (tree2.sum(h1, w1, h1, w1) == 1)
	tree2.add(h1, w1, -1);
    } else {
      cout << tree2.sum(h1, w1, h2, w2) << " " << tree1.sum(h1, w1, h2, w2) << "\n";
    }
  }
}

int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  solve();
  return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 39816
final_rank: 1

code_snippet: #include <bits/stdc++.h>
#define REP(i, n) for(int i = 0; i < (int)(n); ++i)
#define FOR(i, l, r) for(int i = (int)(l); i < (int)(r); ++i)
#define ALL(v) (v).begin(), (v).end()
using llong = long long;
using vi = std::vector<int>;
using vvi = std::vector<vi>;
using pii = std::pair<int, int>;
using namespace std;
constexpr int INF = 1e9;
constexpr long long LINF = 1e18;
constexpr double EPS = 1e-10;
constexpr int MOD = 998'244'353;
constexpr int MOD2 = 1e9 + 7;

template <typename Type>
inline std::istream &operator>>(std::istream &is, std::vector<Type> &v) {
    for(Type &in : v) is >> in;
    return is;
}

template <typename Type>
inline std::ostream &operator<<(std::ostream &os, const std::vector<Type> &v) {
    for(auto itr = v.cbegin(); itr != v.cend(); ++itr) os << (itr == v.cbegin() ? "" : " ") << *itr;
    return os;
}

#ifdef DEBUG

#include "lib/Utils/debug.hpp"
using namespace algorithm;

#else

#define debug(...) static_cast<void>(0)

#endif

// 二次元BIT (0-based index)．
template <typename T>
class BIT2D0 {
    int m_h, m_w;
    std::vector<std::vector<T> > m_tree;  // 0-based index.

    void build() {
        for(int i = 0; i < height(); ++i) {
            int ni = i | (i + 1);
            bool flag = (ni < height());
            for(int j = 0; j < width(); ++j) {
                int nj = j | (j + 1);
                if(nj < width()) {
                    m_tree[i][nj] += m_tree[i][j];
                    if(flag) m_tree[ni][nj] -= m_tree[i][j];
                }
                if(flag) m_tree[ni][j] += m_tree[i][j];
            }
        }
    }

public:
    // constructor. O(H*W).
    BIT2D0() : BIT2D0(0, 0) {}
    explicit BIT2D0(size_t h, size_t w, T a = 0) : m_h(h), m_w(w), m_tree(h, std::vector<T>(w, a)) {
        if(a != 0) build();
    }
    explicit BIT2D0(const std::vector<std::vector<T> > &dat) : m_h(dat.size()), m_w((dat.empty() ? 0 : dat[0].size())), m_tree(dat) {
        build();
    }

    int height() const { return m_h; }
    int width() const { return m_w; }
    // (y,x)にある要素にaを加算する．O((logH)*logW).
    void add(int y, int x, T a) {
        assert(0 <= y and y < height());
        assert(0 <= x and x < width());
        for(int i = y; i < height(); i |= i + 1) {
            for(int j = x; j < width(); j |= j + 1) m_tree[i][j] += a;
        }
    }
    // 区間[0,y)かつ[0,x)の総和を求める．O((logH)*logW).
    T sum(int y, int x) const {
        assert(0 <= y and y <= height());
        assert(0 <= x and x <= width());
        T res = 0;
        for(int i = y - 1; i >= 0; i = (i & (i + 1)) - 1) {
            for(int j = x - 1; j >= 0; j = (j & (j + 1)) - 1) res += m_tree[i][j];
        }
        return res;
    }
    // 区間[y,yy)かつ[x,xx)の総和を求める．O((logH)*logW).
    T sum(int y, int x, int yy, int xx) const {
        assert(0 <= y and y <= yy and yy <= height());
        assert(0 <= x and x <= xx and xx <= width());
        return sum(yy, xx) - sum(yy, x) - sum(y, xx) + sum(y, x);
    }
    // 全要素をaで埋める．O(H*W).
    void fill(T a = 0) {
        for(auto &elem : m_tree) std::fill(elem.begin(), elem.end(), a);
        if(a != 0) build();
    }
};

int main() {
    int y, x;
    int t;
    int q;
    std::cin >> y >> x >> t >> q;

    BIT2D0<int> raw(y, x), baked(y, x);
    std::queue<std::tuple<int, int, int> > que;
    while(q--) {
        int time;
        int c;
        std::cin >> time >> c;

        while(!que.empty()) {
            auto [end, y, x] = que.front();
            if(time < end) break;
            que.pop();

            raw.add(y, x, -1);
            baked.add(y, x, 1);
        }

        if(c == 0) {
            int y, x;
            std::cin >> y >> x;
            y--, x--;

            raw.add(y, x, 1);
            que.emplace(time + t, y, x);
        } else if(c == 1) {
            int y, x;
            std::cin >> y >> x;
            y--, x--;

            if(baked.sum(y, x, y + 1, x + 1) >= 1) baked.add(y, x, -1);
        } else {
            int y, x, yy, xx;
            std::cin >> y >> x >> yy >> xx;
            y--, x--;

            auto a = baked.sum(y, x, yy, xx);
            auto b = raw.sum(y, x, yy, xx);
            std::cout << a << " " << b << "\n";
        }
    }
}
accuracy: 1
time_ms: 230
memory_kb: 35644
final_rank: 10

code_snippet: #include <bits/stdc++.h>
#define REP(i, n) for(int i = 0; i < (int)(n); ++i)
#define FOR(i, l, r) for(int i = (int)(l); i < (int)(r); ++i)
#define ALL(v) (v).begin(), (v).end()
using llong = long long;
using vi = std::vector<int>;
using vvi = std::vector<vi>;
using pii = std::pair<int, int>;
using namespace std;
constexpr int INF = 1e9;
constexpr long long LINF = 1e18;
constexpr double EPS = 1e-10;
constexpr int MOD = 998'244'353;
constexpr int MOD2 = 1e9 + 7;

template <typename Type>
inline std::istream &operator>>(std::istream &is, std::vector<Type> &v) {
    for(Type &in : v) is >> in;
    return is;
}

template <typename Type>
inline std::ostream &operator<<(std::ostream &os, const std::vector<Type> &v) {
    for(auto itr = v.cbegin(); itr != v.cend(); ++itr) os << (itr == v.cbegin() ? "" : " ") << *itr;
    return os;
}

#ifdef DEBUG

#include "lib/Utils/debug.hpp"
using namespace algorithm;

#else

#define debug(...) static_cast<void>(0)

#endif

// 二次元BIT (0-based index)．
template <typename T>
class BIT2D0 {
    int m_h, m_w;
    std::vector<std::vector<T> > m_tree;  // 0-based index.

    void build() {
        for(int i = 0; i < height(); ++i) {
            int ni = i | (i + 1);
            bool flag = (ni < height());
            for(int j = 0; j < width(); ++j) {
                int nj = j | (j + 1);
                if(nj < width()) {
                    m_tree[i][nj] += m_tree[i][j];
                    if(flag) m_tree[ni][nj] -= m_tree[i][j];
                }
                if(flag) m_tree[ni][j] += m_tree[i][j];
            }
        }
    }

public:
    // constructor. O(H*W).
    BIT2D0() : BIT2D0(0, 0) {}
    explicit BIT2D0(size_t h, size_t w, T a = 0) : m_h(h), m_w(w), m_tree(h, std::vector<T>(w, a)) {
        if(a != 0) build();
    }
    explicit BIT2D0(const std::vector<std::vector<T> > &dat) : m_h(dat.size()), m_w((dat.empty() ? 0 : dat[0].size())), m_tree(dat) {
        build();
    }

    int height() const { return m_h; }
    int width() const { return m_w; }
    // dat[x][y]に要素aを加算する．O((logH)*logW).
    void add(int y, int x, T a) {
        assert(0 <= y and y < height());
        assert(0 <= x and x < width());
        for(int i = y; i < height(); i |= i + 1) {
            for(int j = x; j < width(); j |= j + 1) m_tree[i][j] += a;
        }
    }
    // 区間[0,y)かつ[0,x)の総和を求める．O((logH)*logW).
    T sum(int y, int x) const {
        assert(0 <= y and y <= height());
        assert(0 <= x and x <= width());
        T res = 0;
        for(int i = y - 1; i >= 0; i = (i & (i + 1)) - 1) {
            for(int j = x - 1; j >= 0; j = (j & (j + 1)) - 1) res += m_tree[i][j];
        }
        return res;
    }
    // 区間[y,yy)かつ[x,xx)の総和を求める．O((logH)*logW).
    T sum(int y, int x, int yy, int xx) const {
        assert(0 <= y and y <= yy and yy <= height());
        assert(0 <= x and x <= xx and xx <= width());
        return sum(yy, xx) - sum(yy, x) - sum(y, xx) + sum(y, x);
    }
    // 全要素をaで埋める．O(H*W).
    void fill(T a = 0) {
        for(auto &elem : m_tree) std::fill(elem.begin(), elem.end(), a);
        if(a != 0) build();
    }
};

int main() {
    int h, w;
    int time;
    int q;
    cin >> h >> w >> time >> q;

    BIT2D0<int> raw(h, w), baked(h, w);
    queue<tuple<int, int, int> > que;
    while(q--) {
        int t;
        int c;
        cin >> t >> c;

        while(!que.empty()) {
            auto [t2, y, x] = que.front();
            if(t2 > t) break;
            que.pop();

            raw.add(y, x, -1);
            baked.add(y, x, 1);
        }

        if(c == 0) {
            int y, x;
            cin >> y >> x;
            y--, x--;

            raw.add(y, x, 1);
            que.emplace(t + time, y, x);
        } else if(c == 1) {
            int y, x;
            cin >> y >> x;
            y--, x--;

            if(baked.sum(y, x, y + 1, x + 1) > 0) baked.add(y, x, -1);
        } else {
            int y, x, y2, x2;
            cin >> y >> x >> y2 >> x2;
            y--, x--;

            auto a = baked.sum(y, x, y2, x2);
            auto b = raw.sum(y, x, y2, x2);
            cout << a << " " << b << "\n";
        }
    }
}
accuracy: 1
time_ms: 220
memory_kb: 35612
final_rank: 8

code_snippet: #include<bits/stdc++.h>
#define _GLIBCXX_DEBUG
#define OVERLOAD_REP(v1, v2, v3, v4, NAME, ...) NAME
#define REP1(i, n) for (auto i = 0; (i) < (n); ++(i))
#define REP2(i, l, r) for (auto i = (l); (i) < (r); ++(i))
#define REP3(i, l, r, d) for (auto i = (l); (i) < (r); (i)+=(d))
#define rep(...) OVERLOAD_REP(__VA_ARGS__, REP3, REP2, REP1)(__VA_ARGS__)
#define OVERLOAD_PRE(v1, v2, v3, v4, NAME, ...) NAME
#define PRE1(i, n) for (auto i = (n)-1; (i) >= 0; --(i)) //[0,n)
#define PRE2(i, l, r) for (auto i = (r)-1; (i) >= (l); --(i)) //[l,r)
#define PRE3(i, l, r, d) for (auto i = (r)-1; (i) >= (l); (i)-=(d))
#define pre(...) OVERLOAD_PRE(__VA_ARGS__, PRE3, PRE2, PRE1)(__VA_ARGS__)
#define bg begin()
#define en end()
#define rbg rbegin()
#define ren rend()
#define all(x) x.bg,x.en
#define rall(x) x.rbg,x.ren
#define pb push_back
#define eb emplace_back
#define fir first
#define sec second
using namespace std;
using ll = long long;
using ld = long double;
using pii = pair<int,int>;
using pll = pair<ll,ll>;
using si = stack<int>;
using qi = queue<int>;
using qii = queue<pii>;
template<class t> using pql=priority_queue<t>;
template<class t> using pqg=priority_queue<t,vector<t>, greater<t>>;
template<class t> using vc=vector<t>;
template<class t> using vvc=vc<vc<t>>;
template<class t> using vvvc=vc<vc<vc<t>>>;
using vi=vc<int>;
using vvi=vc<vc<int>>;
using vll=vc<ll>;
using vvll=vc<vc<ll>>;
using vd=vc<double>;
using vvd=vc<vc<double>>;
using vb=vc<bool>;
using vvb=vc<vc<bool>>;
using vch=vc<char>;
using vs=vc<string>;
const double PI = 3.141592653589793;
const int inf = 1073741823;
const ll infl = 1LL << 60;
template<class t,class u> bool chmax(t&a,u b){if(a<b){a=b; return true;} return false;}
template<class t,class u> bool chmin(t&a,u b){if(a>b){a=b; return true;} return false;}
void yes(){ cout << "Yes" << endl; }
void no(){ cout << "No" << endl; }

/* BIT_2D:
    初期値は全て 0
    ・add(h,w,x): (h,w) に x を加算する
    ・sum(h,w): 0≦i≦h かつ 0≦j≦w の範囲の合計値を求める
    ・query(h1,w1,h2,w2): h1≦i<h2 かつ w1≦j<w2 の範囲の合計値を求める
    ・get(h1,w1): (h1,w1)を取得
    計算量は全て O(logW * logH)
    print(): デバッグ用
*/
template <typename T>
struct BIT_2D {
    int H, W;
    vector<vector<T>> bit;  // データの格納先
    BIT_2D(int H_, int W_) { init(H_, W_); }
    void init(int H_, int W_) {
        H = H_ + 1;
        W = W_ + 1;
        bit.assign(H, vector<T>(W, 0));
    }
    void add(int h, int w, T x) {
        h++; w++;
        for (int i = h; i < H; i += (i & -i)) {
            for (int j = w; j < W; j += (j & -j)) {
                bit[i][j] += x;
            }
        }
    }
    T sum(int h, int w) {
        h++; w++;
        T s(0);
        for (int i = h; i > 0; i -= (i & -i)) {
            for (int j = w; j > 0; j -= (j & -j)) {
                s += bit[i][j];
            }
        }
        return s;
    }
    // h1≦i≦h2 かつ w1≦j≦w2
    T query(int h1, int w1, int h2, int w2) {
        return sum(h2, w2) - sum(h2, w1-1) - sum(h1-1, w2) + sum(h1-1, w1-1);
    }
    // 0≦i≦h1 かつ 0≦j≦w1
    T query(int h1, int w1) {
        return query(0, 0, h1, w1);
    }
    // (h1,w1)を取得
    T get(int h1, int w1) {
        return query(h1, w1, h1, w1);
    }
    void print(){
        rep(i,H-1){
            rep(j,W-1) cerr << get(i,j) << ' ';
            cerr << endl;
        }
    }
};

int main(){	
	ios::sync_with_stdio(false);
  	cin.tie(0);
    int h,w,t,q; cin >> h >> w >> t >> q;
    queue<pii> qu;
    BIT_2D<int> bit1(h,w),bit2(h,w);
    rep(i,q){
        int time,c,h1,w1; cin >> time >> c >> h1 >> w1;
        h1--; w1--;
        if(c==0){
            bit1.add(h1,w1,1);
            qu.emplace(time+t,h1*w+w1);
        } else {
            while(!qu.empty()){
                auto [finish,num] = qu.front();
                if(finish>time) break;
                qu.pop();
                int ii = num/w, jj = num%w;
                bit1.add(ii,jj,-1);
                bit2.add(ii,jj,1);
            }
            if(c==1){
                if(bit2.get(h1,w1)) bit2.add(h1,w1,-1);
            } else {
                int h2,w2; cin >> h2 >> w2;
                h2--; w2--;
                cout << bit2.query(h1,w1,h2,w2) << ' ' << bit1.query(h1,w1,h2,w2) << endl;
            }
        }
    }
 
	return 0;
}
accuracy: 1
time_ms: 160
memory_kb: 35144
final_rank: 3

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define ALL(v) v.begin(),v.end()
#define dbg(x) cerr << #x << ": " << (x) << endl;
template<class F, class S>
ostream& operator<<(ostream& os, pair<F,S>& p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template<class Iter>
void print(Iter beg, Iter end) {
    for (Iter itr = beg; itr != end; ++itr) {
        cerr << *itr << ' ';
    }
    cerr << '\n';
}
inline bool naraba(bool a, bool b) { return (!a || b); }

struct BIT2d {
    BIT2d(int h, int w) : H(h), W(w), dat(h+1, vector<ll>(w+1, 0)) {}

    void add(int x, int y, ll val) {
        ++x; ++y;
        for (int a = y; a <= H; a += a & -a) {
            for (int b = x; b <= W; b += b & -b) {
                dat[a][b] += val;
            }
        }
    }

    ll sum(int x, int y) {
        ll s = 0;
        for (int a = y; a > 0; a -= a & -a) {
            for (int b = x; b > 0; b -= b & -b) {
                s += dat[a][b];
            }
        }
        return s;
    }

    ll sum(int x1, int y1, int x2, int y2) {
        if (x1 > x2 || y1 > y2) return 0;
        return sum(x2,y2) - sum(x2,y1) - sum(x1,y2) + sum(x1,y1);
    }

    int H,W;
    vector<vector<ll>> dat;
};

int main() {
    ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20); cerr << fixed << setprecision(6);
    int h,w,T,q;
    cin >> h >> w >> T >> q;
    BIT2d yet(h,w), ok(h,w);
    queue<array<int,3>> move;
    while (q--) {
        int t,c;
        cin >> t >> c;
        while (move.size() && move.front()[0] <= t) {
            int x = move.front()[1];
            int y = move.front()[2];
            assert(yet.sum(x,y,x+1,y+1) > 0);
            yet.add(x,y,-1);
            ok.add(x,y,1);
            move.pop();
        }

        if (c == 0) {
            int x,y;
            cin >> y >> x;
            --y; --x;
            yet.add(x,y,1);
            move.push({t+T, x, y});
        } else if (c == 1) {
            int x,y;
            cin >> y >> x;
            --y; --x;
            if (ok.sum(x,y,x+1,y+1) > 0) {
                ok.add(x,y,-1);
            }
        } else if (c == 2) {
            int x1,y1,x2,y2;
            cin >> y1 >> x1 >> y2 >> x2;
            --x1; --y1;
            cout << ok.sum(x1,y1,x2,y2) << ' ' << yet.sum(x1,y1,x2,y2) << '\n';
        }
    }
}
accuracy: 1
time_ms: 110
memory_kb: 66804
final_rank: 4

code_snippet: #include<bits/stdc++.h>
using namespace std;
template<typename S, auto op, auto e>
struct segtree_2d
{
    segtree_2d():segtree_2d(0,0){}
    segtree_2d(int _h, int _w):segtree_2d(vector<vector<S>>(_h,vector(_w,e()))){}
    segtree_2d(const vector<vector<S>>&v):h(v.size()),w(v[0].size())
    {
        logh=0,logw=0;
        while((1<<logh)<h)logh++;
        while((1<<logw)<w)logw++;
        szh=1<<logh,szw=1<<logw;
        node=vector<vector<S>>(2*szh,vector<S>(2*szw,e()));
        for(int i=0;i<h;i++)for(int j=0;j<w;j++)node[i+szh][j+szw]=v[i][j];
        for(int j=szw;j<2*szw;j++)for(int i=szh-1;i>=1;i--)update_w(i,j);
        for(int i=0;i<2*szh;i++)for(int j=szw-1;j>=1;j--)update_h(i,j);
    }
    void set(int p, int q, S x)
    {
        assert(0<=p&&p<h);
        assert(0<=q&&q<w);
        p+=szh,q+=szw;
        node[p][q]=x;
        for(int j=1;j<=logw;j++)update_h(p,q>>j);
        for(int i=1;i<=logh;i++)
        {
            update_w(p>>i,q);
            for(int j=1;j<=logw;j++)update_h(p>>i,q>>j);
        }
    }
    S get(int p, int q)const
    {
        assert(0<=p&&p<h);
        assert(0<=q&&q<w);
        p+=szh,q+=szw;
        return node[p][q];
    }
    S prod(int d, int l, int u, int r)const
    {
        assert(0<=d&&d<=u&&u<=h);
        assert(0<=l&&l<=r&&r<=w);
        d+=szh,u+=szh;
        l+=szw,r+=szw;
        S pd=e(),pu=e();
        while(d<u)
        {
            if(d&1)pd=op(pd,inner_prod(d++,l,r));
            if(u&1)pu=op(inner_prod(--u,l,r),pu);
            d>>=1,u>>=1;
        }
        return op(pu,pd);
    }
    S all_prod()const{return node[1][1];}
private:
    int h,w,logh,logw,szh,szw;
    vector<vector<S>>node;
    void update_h(int p, int q){node[p][q]=op(node[p][2*q],node[p][2*q+1]);}
    void update_w(int p, int q){node[p][q]=op(node[2*p][q],node[2*p+1][q]);}
    S inner_prod(int p, int l, int r)const
    {
        S pl=e(),pr=e();
        while(l<r)
        {
            if(l&1)pl=op(pl,node[p][l++]);
            if(r&1)pr=op(node[p][--r],pr);
            l>>=1,r>>=1;
        }
        return op(pl,pr);
    }
};
pair<int,int> op(pair<int,int> a, pair<int,int> b){return make_pair(a.first+b.first,a.second+b.second);}
pair<int,int> e(){return make_pair(0,0);}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int H,W,T,Q;
    cin>>H>>W>>T>>Q;
    segtree_2d<pair<int,int>,op,e>seg(H,W);
    priority_queue<pair<int,pair<int,int>>,vector<pair<int,pair<int,int>>>,greater<pair<int,pair<int,int>>>>q;
    while(Q--)
    {
        int t,c;
        cin>>t>>c;
        while(!q.empty()&&q.top().first<=t)
        {
            auto[h,w]=q.top().second;
            q.pop();
            auto[ok,ng]=seg.get(h,w);
            assert(ng>0);
            seg.set(h,w,make_pair(ok+1,ng-1));
        }
        if(c==0)
        {
            int h,w;
            cin>>h>>w;
            h--,w--;
            q.push(make_pair(t+T,make_pair(h,w)));
            auto[ok,ng]=seg.get(h,w);
            seg.set(h,w,make_pair(ok,ng+1));
        }
        else if(c==1)
        {
            int h,w;
            cin>>h>>w;
            h--,w--;
            auto[ok,ng]=seg.get(h,w);
            if(ok>0)ok--;
            seg.set(h,w,make_pair(ok,ng));
        }
        else
        {
            int h1,w1,h2,w2;
            cin>>h1>>w1>>h2>>w2;
            h1--,w1--;
            auto[ok,ng]=seg.prod(h1,w1,h2,w2);
            cout<<ok<<' '<<ng<<'\n';
        }
    }
}
accuracy: 1
time_ms: 300
memory_kb: 165712
final_rank: 15

code_snippet: #include<bits/stdc++.h>
using namespace std;
template<typename S, S (*op)(S,S), S (*e)()>
struct segtree_2d
{
    segtree_2d():segtree_2d(0,0){}
    segtree_2d(int h_, int w_):segtree_2d(vector<vector<S>>(h_,vector<S>(w_,e()))){}
    segtree_2d(vector<vector<S>>v):h(v.size()),w(v[0].size())
    {
        logh=0,logw=0;
        while((1<<logh)<h)logh++;
        while((1<<logw)<w)logw++;
        szh=1<<logh,szw=1<<logw;
        node.resize(4*szh*szw,e());
        for(int i=0;i<h;i++)for(int j=0;j<w;j++)node[idx(i+szh,j+szw)]=v[i][j];
        for(int j=szw;j<2*szw;j++)for(int i=szh-1;i>=1;i--)update_w(i,j);
        for(int i=0;i<2*szh;i++)for(int j=szw-1;j>=1;j--)update_h(i,j);
    }
    void set(int p, int q, S x)
    {
        assert(0<=p&&p<h);
        assert(0<=q&&q<w);
        p+=szh,q+=szw;
        node[idx(p,q)]=x;
        int i=p,j=q;
        for(int j=1;j<=logw;j++)update_h(p,q>>j);
        for(int i=1;i<=logh;i++)
        {
            update_w(p>>i,q);
            for(int j=1;j<=logw;j++)update_h(p>>i,q>>j);
        }
    }
    S get(int p, int q)
    {
        assert(0<=p&&p<h);
        assert(0<=q&&q<w);
        p+=szh,q+=szw;
        return node[idx(p,q)];
    }
    S prod(int d, int l, int u, int r)
    {
        assert(0<=d&&d<=u&&u<=h);
        assert(0<=l&&l<=r&&r<=w);
        d+=szh,u+=szh;
        l+=szw,r+=szw;
        S pd=e(),pu=e();
        while(d<u)
        {
            if(d&1)pd=op(pd,inner_prod(d++,l,r));
            if(u&1)pu=op(inner_prod(--u,l,r),pu);
            d>>=1,u>>=1;
        }
        return op(pd,pu);
    }
    S all_prod(){return node[idx(1,1)];}
private:
    int h,w,logh,logw,szh,szw;
    vector<S>node;
    int idx(int p, int q){return 2*p*szw+q;}
    void update_h(int p, int q){node[idx(p,q)]=op(node[idx(p,2*q)],node[idx(p,2*q+1)]);}
    void update_w(int p, int q){node[idx(p,q)]=op(node[idx(2*p,q)],node[idx(2*p+1,q)]);}
    S inner_prod(int p, int l, int r)
    {
        S pl=e(),pr=e();
        while(l<r)
        {
            if(l&1)pl=op(pl,node[idx(p,l++)]);
            if(r&1)pr=op(node[idx(p,--r)],pr);
            l>>=1,r>>=1;
        }
        return op(pl,pr);
    }
};
pair<int,int> op(pair<int,int> a, pair<int,int> b){return make_pair(a.first+b.first,a.second+b.second);}
pair<int,int> e(){return make_pair(0,0);}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int H,W,T,Q;
    cin>>H>>W>>T>>Q;
    segtree_2d<pair<int,int>,op,e>seg(H,W);
    priority_queue<pair<int,pair<int,int>>,vector<pair<int,pair<int,int>>>,greater<pair<int,pair<int,int>>>>q;
    while(Q--)
    {
        int t,c;
        cin>>t>>c;
        while(!q.empty()&&q.top().first<=t)
        {
            auto[h,w]=q.top().second;
            q.pop();
            auto[ok,ng]=seg.get(h,w);
            assert(ng>0);
            seg.set(h,w,make_pair(ok+1,ng-1));
        }
        if(c==0)
        {
            int h,w;
            cin>>h>>w;
            h--,w--;
            q.push(make_pair(t+T,make_pair(h,w)));
            auto[ok,ng]=seg.get(h,w);
            seg.set(h,w,make_pair(ok,ng+1));
        }
        else if(c==1)
        {
            int h,w;
            cin>>h>>w;
            h--,w--;
            auto[ok,ng]=seg.get(h,w);
            if(ok>0)ok--;
            seg.set(h,w,make_pair(ok,ng));
        }
        else
        {
            int h1,w1,h2,w2;
            cin>>h1>>w1>>h2>>w2;
            h1--,w1--;
            auto[ok,ng]=seg.prod(h1,w1,h2,w2);
            cout<<ok<<' '<<ng<<'\n';
        }
    }
}
accuracy: 1
time_ms: 330
memory_kb: 165656
final_rank: 17

code_snippet: #include<bits/stdc++.h>
using namespace std;
template<typename S, auto op, auto e>
struct segtree_2d
{
    segtree_2d():segtree_2d(0,0){}
    segtree_2d(int h_, int w_):segtree_2d(vector<vector<S>>(h_,vector<S>(w_,e()))){}
    segtree_2d(vector<vector<S>>v):h(v.size()),w(v[0].size())
    {
        logh=0,logw=0;
        while((1<<logh)<h)logh++;
        while((1<<logw)<w)logw++;
        szh=1<<logh,szw=1<<logw;
        node.resize(4*szh*szw,e());
        for(int i=0;i<h;i++)for(int j=0;j<w;j++)node[idx(i+szh,j+szw)]=v[i][j];
        for(int j=szw;j<2*szw;j++)for(int i=szh-1;i>=1;i--)update_w(i,j);
        for(int i=0;i<2*szh;i++)for(int j=szw-1;j>=1;j--)update_h(i,j);
    }
    void set(int p, int q, S x)
    {
        assert(0<=p&&p<h);
        assert(0<=q&&q<w);
        p+=szh,q+=szw;
        node[idx(p,q)]=x;
        int i=p,j=q;
        for(int j=1;j<=logw;j++)update_h(p,q>>j);
        for(int i=1;i<=logh;i++)
        {
            update_w(p>>i,q);
            for(int j=1;j<=logw;j++)update_h(p>>i,q>>j);
        }
    }
    S get(int p, int q)
    {
        assert(0<=p&&p<h);
        assert(0<=q&&q<w);
        p+=szh,q+=szw;
        return node[idx(p,q)];
    }
    S prod(int d, int l, int u, int r)
    {
        assert(0<=d&&d<=u&&u<=h);
        assert(0<=l&&l<=r&&r<=w);
        d+=szh,u+=szh;
        l+=szw,r+=szw;
        S pd=e(),pu=e();
        while(d<u)
        {
            if(d&1)pd=op(pd,inner_prod(d++,l,r));
            if(u&1)pu=op(inner_prod(--u,l,r),pu);
            d>>=1,u>>=1;
        }
        return op(pd,pu);
    }
    S all_prod(){return node[idx(1,1)];}
private:
    int h,w,logh,logw,szh,szw;
    vector<S>node;
    int idx(int p, int q){return 2*p*szw+q;}
    void update_h(int p, int q){node[idx(p,q)]=op(node[idx(p,2*q)],node[idx(p,2*q+1)]);}
    void update_w(int p, int q){node[idx(p,q)]=op(node[idx(2*p,q)],node[idx(2*p+1,q)]);}
    S inner_prod(int p, int l, int r)
    {
        S pl=e(),pr=e();
        while(l<r)
        {
            if(l&1)pl=op(pl,node[idx(p,l++)]);
            if(r&1)pr=op(node[idx(p,--r)],pr);
            l>>=1,r>>=1;
        }
        return op(pl,pr);
    }
};
pair<int,int> op(pair<int,int> a, pair<int,int> b){return make_pair(a.first+b.first,a.second+b.second);}
pair<int,int> e(){return make_pair(0,0);}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int H,W,T,Q;
    cin>>H>>W>>T>>Q;
    segtree_2d<pair<int,int>,op,e>seg(H,W);
    priority_queue<pair<int,pair<int,int>>,vector<pair<int,pair<int,int>>>,greater<pair<int,pair<int,int>>>>q;
    while(Q--)
    {
        int t,c;
        cin>>t>>c;
        while(!q.empty()&&q.top().first<=t)
        {
            auto[h,w]=q.top().second;
            q.pop();
            auto[ok,ng]=seg.get(h,w);
            assert(ng>0);
            seg.set(h,w,make_pair(ok+1,ng-1));
        }
        if(c==0)
        {
            int h,w;
            cin>>h>>w;
            h--,w--;
            q.push(make_pair(t+T,make_pair(h,w)));
            auto[ok,ng]=seg.get(h,w);
            seg.set(h,w,make_pair(ok,ng+1));
        }
        else if(c==1)
        {
            int h,w;
            cin>>h>>w;
            h--,w--;
            auto[ok,ng]=seg.get(h,w);
            if(ok>0)ok--;
            seg.set(h,w,make_pair(ok,ng));
        }
        else
        {
            int h1,w1,h2,w2;
            cin>>h1>>w1>>h2>>w2;
            h1--,w1--;
            auto[ok,ng]=seg.prod(h1,w1,h2,w2);
            cout<<ok<<' '<<ng<<'\n';
        }
    }
}
accuracy: 1
time_ms: 330
memory_kb: 165648
final_rank: 16

code_snippet: #include<bits/stdc++.h>
using namespace std;
template<typename S, auto op, auto e>
struct segtree_2d
{
    segtree_2d():segtree_2d(0,0){}
    segtree_2d(int h_, int w_):segtree_2d(vector<vector<S>>(h_,vector<S>(w_,e()))){}
    segtree_2d(vector<vector<S>>v):h(v.size()),w(v[0].size())
    {
        logh=0,logw=0;
        while((1<<logh)<h)logh++;
        while((1<<logw)<w)logw++;
        szh=1<<logh,szw=1<<logw;
        node.resize(4*szh*szw,e());
        for(int i=0;i<h;i++)for(int j=0;j<w;j++)node[idx(i+szh,j+szw)]=v[i][j];
        for(int j=szw;j<2*szw;j++)for(int i=szh-1;i>=1;i--)update_w(i,j);
        for(int i=0;i<2*szh;i++)for(int j=szw-1;j>=1;j--)update_h(i,j);
    }
    void set(int p, int q, S x)
    {
        assert(0<=p&&p<h);
        assert(0<=q&&q<w);
        p+=szh,q+=szw;
        node[idx(p,q)]=x;
        int i=p,j=q;
        for(int j=1;j<=logw;j++)update_h(p,q>>j);
        for(int i=1;i<=logh;i++)
        {
            update_w(p>>i,q);
            for(int j=1;j<=logw;j++)update_h(p>>i,q>>j);
        }
    }
    S get(int p, int q)
    {
        assert(0<=p&&p<h);
        assert(0<=q&&q<w);
        p+=szh,q+=szw;
        return node[idx(p,q)];
    }
    S prod(int d, int l, int u, int r)
    {
        assert(0<=d&&d<=u&&u<=h);
        assert(0<=l&&l<=r&&r<=w);
        d+=szh,u+=szh;
        l+=szw,r+=szw;
        S pd=e(),pu=e();
        while(d<u)
        {
            if(d&1)pd=op(pd,inner_prod(d++,l,r));
            if(u&1)pu=op(inner_prod(--u,l,r),pu);
            d>>=1,u>>=1;
        }
        return op(pd,pu);
    }
    S all_prod(){return node[idx(1,1)];}
private:
    int h,w,logh,logw,szh,szw;
    vector<S>node;
    int idx(int p, int q){return 2*p*szw+q;}
    void update_h(int p, int q){node[idx(p,q)]=op(node[idx(p,2*q)],node[idx(p,2*q+1)]);}
    void update_w(int p, int q){node[idx(p,q)]=op(node[idx(2*p,q)],node[idx(2*p+1,q)]);}
    S inner_prod(int p, int l, int r)
    {
        S pl=e(),pr=e();
        while(l<r)
        {
            if(l&1)pl=op(pl,node[idx(p,l++)]);
            if(r&1)pr=op(node[idx(p,--r)],pr);
            l>>=1,r>>=1;
        }
        return op(pl,pr);
    }
};
pair<int,int> op(pair<int,int> a, pair<int,int> b){return make_pair(a.first+b.first,a.second+b.second);}
pair<int,int> e(){return make_pair(0,0);}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int H,W,T,Q;
    cin>>H>>W>>T>>Q;
    segtree_2d<pair<int,int>,op,e>seg(H,W);
    priority_queue<pair<int,pair<int,int>>,vector<pair<int,pair<int,int>>>,greater<pair<int,pair<int,int>>>>q;
    while(Q--)
    {
        int t,c;
        cin>>t>>c;
        while(!q.empty()&&q.top().first<=t)
        {
            auto[h,w]=q.top().second;
            q.pop();
            auto[ok,ng]=seg.get(h,w);
            assert(ng>0);
            seg.set(h,w,make_pair(ok+1,ng-1));
        }
        if(c==0)
        {
            int h,w;
            cin>>h>>w;
            h--,w--;
            q.push(make_pair(t+T,make_pair(h,w)));
            auto[ok,ng]=seg.get(h,w);
            seg.set(h,w,make_pair(ok,ng+1));
        }
        else if(c==1)
        {
            int h,w;
            cin>>h>>w;
            h--,w--;
            auto[ok,ng]=seg.get(h,w);
            if(ok>0)ok--;
            seg.set(h,w,make_pair(ok,ng));
        }
        else
        {
            int h1,w1,h2,w2;
            cin>>h1>>w1>>h2>>w2;
            h1--,w1--;
            auto[ok,ng]=seg.prod(h1,w1,h2,w2);
            cout<<ok<<' '<<ng<<'\n';
        }
    }
}
accuracy: 1
time_ms: 340
memory_kb: 165616
final_rank: 18

code_snippet: #include<bits/stdc++.h>
using namespace std;
template<typename S, auto op, auto e>
struct segtree_2d
{
    segtree_2d():segtree_2d(0,0){}
    segtree_2d(int h_, int w_):segtree_2d(vector<vector<S>>(h_,vector<S>(w_,e()))){}
    segtree_2d(vector<vector<S>>v):h(v.size()),w(v[0].size())
    {
        logh=0,logw=0;
        while((1<<logh)<h)logh++;
        while((1<<logw)<w)logw++;
        szh=1<<logh,szw=1<<logw;
        node.resize(4*szh*szw,e());
        for(int i=0;i<h;i++)for(int j=0;j<w;j++)node[idx(i+szh,j+szw)]=v[i][j];
        for(int j=szw;j<2*szw;j++)for(int i=szh-1;i>=1;i--)update_h(i,j);
        for(int i=0;i<2*szh;i++)for(int j=szw-1;j>=1;j--)update_w(i,j);
    }
    void set(int p, int q, S x)
    {
        assert(0<=p&&p<h);
        assert(0<=q&&q<w);
        p+=szh,q+=szw;
        node[idx(p,q)]=x;
        for(int i=1;i<logh;i++)update_h(p>>i,q);
        for(int i=0;i<logh;i++)for(int j=1;j<logw;j++)update_w(p>>i,q>>j);
    }
    S get(int p, int q)
    {
        assert(0<=p&&p<h);
        assert(0<=q&&q<w);
        p+=szh,q+=szw;
        return node[idx(p,q)];
    }
    S prod(int d, int l, int u, int r)
    {
        assert(0<=d&&d<=u&&u<=h);
        assert(0<=l&&l<=r&&r<=w);
        d+=szh,u+=szh;
        l+=szw,r+=szw;
        S pd=e(),pu=e();
        while(d<u)
        {
            if(d&1)pd=op(pd,inner_prod(d++,l,r));
            if(u&1)pu=op(inner_prod(--u,l,r),pu);
            d>>=1,u>>=1;
        }
        return op(pd,pu);
    }
    S all_prod(){return node[1];}
private:
    int h,w,logh,logw,szh,szw;
    vector<S>node;
    int idx(int p, int q){return 2*p*szw+q;}
    void update_h(int p, int q){node[idx(p,q)]=op(node[idx(2*p,q)],node[idx(2*p+1,q)]);}
    void update_w(int p, int q){node[idx(p,q)]=op(node[idx(p,2*q)],node[idx(p,2*q+1)]);}
    S inner_prod(int p, int l, int r)
    {
        S pl=e(),pr=e();
        while(l<r)
        {
            if(l&1)pl=op(pl,node[idx(p,l++)]);
            if(r&1)pr=op(node[idx(p,--r)],pr);
            l>>=1,r>>=1;
        }
        return op(pl,pr);
    }
};
pair<int,int> op(pair<int,int> a, pair<int,int> b){return make_pair(a.first+b.first,a.second+b.second);}
pair<int,int> e(){return make_pair(0,0);}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int H,W,T,Q;
    cin>>H>>W>>T>>Q;
    segtree_2d<pair<int,int>,op,e>seg(H,W);
    priority_queue<pair<int,pair<int,int>>,vector<pair<int,pair<int,int>>>,greater<pair<int,pair<int,int>>>>q;
    while(Q--)
    {
        int t,c;
        cin>>t>>c;
        while(!q.empty()&&q.top().first<=t)
        {
            auto[h,w]=q.top().second;
            q.pop();
            auto[ok,ng]=seg.get(h,w);
            assert(ng>0);
            seg.set(h,w,make_pair(ok+1,ng-1));
        }
        if(c==0)
        {
            int h,w;
            cin>>h>>w;
            h--,w--;
            q.push(make_pair(t+T,make_pair(h,w)));
            auto[ok,ng]=seg.get(h,w);
            seg.set(h,w,make_pair(ok,ng+1));
        }
        else if(c==1)
        {
            int h,w;
            cin>>h>>w;
            h--,w--;
            auto[ok,ng]=seg.get(h,w);
            if(ok>0)ok--;
            seg.set(h,w,make_pair(ok,ng));
        }
        else
        {
            int h1,w1,h2,w2;
            cin>>h1>>w1>>h2>>w2;
            h1--,w1--;
            auto[ok,ng]=seg.prod(h1,w1,h2,w2);
            cout<<ok<<' '<<ng<<'\n';
        }
    }
}
accuracy: 0.8409090909090909
time_ms: 310
memory_kb: 165652
final_rank: 19

code_snippet: #if 1
#include<cmath>
#include<limits>
#include<iostream>
#include<algorithm>
#include<functional>
#include<string>
#include<map>
#include<set>
#include<ctime>
#include<queue>
#include<vector>
#include<complex>
#include<tuple>
#ifdef _INTEGRAL_MAX_BITS
// #include"C:\Users\Spare\source\repos\Competitive_programming\Competitive_programming\debugging.h"
#endif
#ifndef DEBUGGING
#define MY_MAIN int main()
#define REDIRCT_IO
#define RESTORE_IO
#endif
#define sc static
#define ct const
#define ft first
#define sd second
using namespace std;
// using namespace atcoder;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef long double ld;
typedef long long ll;
typedef const int cint;
typedef const ll cll;
typedef const uint cuint;
typedef const ull cull;
inline void scan() {}
typedef int TYPE;
static const TYPE INF = numeric_limits<TYPE>::max();
#define rep(i, n) for(int i = (0), fend = n; i < fend; ++i)
// #define rep2(i, s, e) for(int i = s, fend = e; i < fend; ++i)
static const char ascii_lowercase[26] = { 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z' };
static const char ascii_uppercase[26] = { 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z' };
using V = vector<int>;
cint maxT = 100'000;
int H, W, T, Q; /*tuple<int, int, int, int> event[maxT];*/
priority_queue<V, vector<V>, greater<V>> event;
template<typename T>
struct BIT2D {
    int H, W;
    vector<vector<T>>bit;
    BIT2D(int H_, int W_) { init(H_, W_); }
    void init(int H_, int W_) {
        H = H_ + 1;
        W = W_ + 1;
        bit.assign(H, vector<T>(W, 0));
    }

    void add(int h, int w, T x) {
        for (int i = h; i < H; i += (i & -i)) {
            for (int j = w; j < W; j += (j & -j)) {
                bit[i][j] += x;
            }
        }
    }

    T sum(int h, int w) {
        T s(0);
        for (int i = h; i > 0; i -= (i & -i)) {
            for (int j = w; j > 0; j -= (j & -j)) {
                s += bit[i][j];
            }
        }
        return s;
    }
    T query(int h1, int w1, int h2, int w2) {
        return sum(h2, w2) - sum(h2, w1-1) - sum(h1-1, w2) + sum(h1-1, w1-1);
    }
};

MY_MAIN{
    REDIRCT_IO;
    cin >> H >> W >> T >> Q;
    rep(i, Q) {
        int t, c, h1, w1, h2, w2;
        cin >> t >> c;
        ++c;
        if (c == 3) {
            cin >> h1 >> w1 >> h2 >> w2;
            event.push(V({ t, c, h1, w1, h2, w2 }));
        }
        else {
            cin >> h1 >> w1;
            event.push(V({ t, c, h1, w1 }));
        }
    }
    BIT2D<int>* row(new BIT2D<int>(H, W)), *baked(new BIT2D<int>(H,W));
    while (!event.empty()) {
        V v = event.top();
        event.pop();
        switch (v[1]) {
        case 0:
            row->add(v[2], v[3], -1);
            baked->add(v[2], v[3], 1);
            break;
        case 1:
            row->add(v[2], v[3], 1);
            event.push(V({ v[0] + T, 0, v[2], v[3] }));
            break;
        case 2:
            if (baked->query(v[2], v[3], v[2], v[3]) > 0) {
                baked->add(v[2], v[3], -1);
            }
            break;
        case 3:
            cout << baked->query(v[2], v[3], v[4], v[5]) << ' ' << row->query(v[2], v[3], v[4], v[5]) << '\n';
            break;       
        }
    }
    delete row;
    delete baked;
    RESTORE_IO;
    return 0;
}
#endif
accuracy: 1
time_ms: 170
memory_kb: 40804
final_rank: 5

code_snippet: #if 1
#include<cmath>
#include<limits>
#include<iostream>
#include<algorithm>
#include<functional>
#include<string>
#include<map>
#include<set>
#include<ctime>
#include<queue>
#include<vector>
#include<complex>
#include<tuple>
#ifdef _INTEGRAL_MAX_BITS
// #include"C:\Users\Spare\source\repos\Competitive_programming\Competitive_programming\debugging.h"
#endif
#ifndef DEBUGGING
#define MY_MAIN int main()
#define REDIRCT_IO
#define RESTORE_IO
#endif
#define sc static
#define ct const
#define ft first
#define sd second
using namespace std;
// using namespace atcoder;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef long double ld;
typedef long long ll;
typedef const int cint;
typedef const ll cll;
typedef const uint cuint;
typedef const ull cull;
inline void scan() {}
typedef int TYPE;
static const TYPE INF = numeric_limits<TYPE>::max();
#define rep(i, n) for(int i = (0), fend = n; i < fend; ++i)
// #define rep2(i, s, e) for(int i = s, fend = e; i < fend; ++i)
static const char ascii_lowercase[26] = { 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z' };
static const char ascii_uppercase[26] = { 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z' };
using V = vector<int>;
cint maxT = 100'000;
int H, W, T, Q; /*tuple<int, int, int, int> event[maxT];*/
priority_queue<V, vector<V>, greater<V>> event;
template<typename T>
struct BIT2D {
    int H, W;
    vector<vector<T>>bit;
    BIT2D(int H_, int W_) { init(H_, W_); }
    void init(int H_, int W_) {
        H = H_ + 1;
        W = W_ + 1;
        bit.assign(H, vector<T>(W, 0));
    }

    void add(int h, int w, T x) {
        for (int i = h; i < H; i += (i & -i)) {
            for (int j = w; j < W; j += (j & -j)) {
                bit[i][j] += x;
            }
        }
    }

    T sum(int h, int w) {
        T s(0);
        for (int i = h; i > 0; i -= (i & -i)) {
            for (int j = w; j > 0; j -= (j & -j)) {
                s += bit[i][j];
            }
        }
        return s;
    }
    T query(int h1, int w1, int h2, int w2) {
        return sum(h2, w2) - sum(h2, w1-1) - sum(h1-1, w2) + sum(h1-1, w1-1);
    }
};

MY_MAIN{
    REDIRCT_IO;
    cin >> H >> W >> T >> Q;
    rep(i, Q) {
        int t, c, h1, w1, h2, w2;
        cin >> t >> c;
        if (c == 2) {
            cin >> h1 >> w1 >> h2 >> w2;
            event.push(V({ t, c, h1, w1, h2, w2 }));
        }
        else {
            cin >> h1 >> w1;
            event.push(V({ t, c, h1, w1 }));
        }
    }
    BIT2D<int>* row(new BIT2D<int>(H, W)), *baked(new BIT2D<int>(H,W));
    while (!event.empty()) {
        V v = event.top();
        event.pop();
        switch (v[1]) {
        case 0:
            row->add(v[2], v[3], 1);
            event.push(V({ v[0] + T, 3, v[2], v[3] }));
            break;
        case 1:
            if (baked->query(v[2], v[3], v[2], v[3]) > 0) {
                baked->add(v[2], v[3], -1);
            }
            break;
        case 2:
            cout << baked->query(v[2], v[3], v[4], v[5]) << ' ' << row->query(v[2], v[3], v[4], v[5]) << '\n';
            break;
        case 3:
            row->add(v[2], v[3], -1);
            baked->add(v[2], v[3], 1);
        }
    }
    delete row;
    delete baked;
    RESTORE_IO;
    return 0;
}
#endif
accuracy: 0.6818181818181818
time_ms: 170
memory_kb: 40624
final_rank: 20

code_snippet: #include <bits/stdc++.h>
using namespace std;

template<class T> struct BIT2D {
  int h, w;
  vector<vector<T>> data;
  BIT2D(int _h, int _w) : h(_h), w(_w), data(_h + 1, vector<T>(_w + 1, 0)) {}
  
  void add(int y, int x, T v) {
    assert(0 <= y && y < h);
    assert(0 <= x && x < w);
    y++; x++;
    for(int i = y; i <= h; i += i & -i){
      for(int j = x; j <= w; j += j & -j){
        data[i - 1][j - 1] += v;
      }
    }
  }
  
  void set(int y, int x, T v) {
    assert(0 <= y && y < h);
    assert(0 <= x && x < w);
    T prev = sum(y, x, y + 1, x + 1);
    add(y, x, v - prev);
  }
  
  T sum(int y, int x) {
    T s = 0;
    for(int i = y; i > 0; i -= i & -i){
      for(int j = x; j > 0; j -= j & -j){
        s += data[i - 1][j - 1];
      }
    }
    return s;
  }
  
  T sum(int h1, int w1, int h2, int w2) {
    assert(0 <= h1 && h1 < h);
    assert(0 <= w1 && w1 < w);
    assert(0 < h2 && h2 <= h);
    assert(0 < w2 && w2 <= w);
    assert(h1 < h2);
    assert(w1 < w2);
    return sum(h2, w2) - sum(h2, w1) - sum(h1, w2) + sum(h1, w1);
  }
  
  void print() {
    for(int i = 0; i < h-1; i++) {
      for(int j = 0; j < w-1; j++) {
        cout << sum(i, j, i+1, j+1) << ",";
      }
      cout << endl;
    }
  }
};
int main() {
  int H, W, T, Q; cin >> H >> W >> T >> Q;
  BIT2D<int> fin(H, W), mada(H, W);
  queue<array<int, 3>> que;
  for (int query = 0; query < Q; ++query) {
    int t, c, h, w; cin >> t >> c >> h >> w;
    h--; w--;
    while (!que.empty()) {
      array<int, 3> a = que.front();
      if (a[0] > t) break;
      que.pop();
      int x = a[1], y = a[2];
      mada.add(x, y, -1);
      fin.add(x, y, 1);
    }
    if (c == 0) {
      mada.set(h, w, 1);
      que.push({t+T, h, w});
    }
    else if (c == 1) {
      if (fin.sum(h, w, h+1, w+1) == 1) fin.add(h, w, -1);
    }
    else {
      int h2, w2; cin >> h2 >> w2;
      h2--; w2--;
      cout << fin.sum(h, w, h2+1, w2+1) << " " << mada.sum(h, w, h2+1, w2+1) << endl;
    }
  }
}
accuracy: 1
time_ms: 220
memory_kb: 35640
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;

template<class T> struct BIT2D {
  int h, w;
  vector<vector<T>> data;
  BIT2D(int _h, int _w) : h(_h), w(_w), data(_h + 1, vector<T>(_w + 1, 0)) {}
  
  void add(int a, int b, T v) {
    assert(0 <= a && a < h);
    assert(0 <= b && b < w);
    a++;
    b++;
    for(int y = a; y <= h; y += y & -y){
      for(int x = b; x <= w; x += x & -x){
        data[y - 1][x - 1] += v;
      }
    }
  }
  
  void set(int a, int b, T v) {
    assert(0 <= a && a < h);
    assert(0 <= b && b < w);
    T prev = sum(a, b, a + 1, b + 1);
    add(a, b, v - prev);
  }
  
  T sum(int a, int b) {
    T s = 0;
    for(int y = a; y > 0; y -= y & -y){
      for(int x = b; x > 0; x -= x & -x){
        s += data[y - 1][x - 1];
      }
    }
    return s;
  }
  
  T sum(int h1, int w1, int h2, int w2) {
    assert(0 <= h1 && h1 < h);
    assert(0 <= w1 && w1 < w);
    assert(0 < h2 && h2 <= h);
    assert(0 < w2 && w2 <= w);
    assert(h1 < h2);
    assert(w1 < w2);
    return sum(h2, w2) - sum(h2, w1) - sum(h1, w2) + sum(h1, w1);
  }
};
int main() {
  int H, W, T, Q; cin >> H >> W >> T >> Q;
  BIT2D<int> fin(H, W), mada(H, W);
  queue<array<int, 3>> que;
  for (int query = 0; query < Q; ++query) {
    int t, c, h, w; cin >> t >> c >> h >> w;
    h--; w--;
    while (!que.empty()) {
      array<int, 3> a = que.front();
      if (a[0] > t) break;
      que.pop();
      int x = a[1], y = a[2];
      mada.add(x, y, -1);
      fin.add(x, y, 1);
    }
    if (c == 0) {
      mada.set(h, w, 1);
      que.push({t+T, h, w});
    }
    else if (c == 1) {
      if (fin.sum(h, w, h+1, w+1) == 1) fin.add(h, w, -1);
    }
    else {
      int h2, w2; cin >> h2 >> w2;
      h2--; w2--;
      cout << fin.sum(h, w, h2+1, w2+1) << " " << mada.sum(h, w, h2+1, w2+1) << endl;
    }
  }
}
accuracy: 1
time_ms: 210
memory_kb: 35688
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;

template<class T> struct BIT2D {
  int h, w;
  vector<vector<T>> data;
  BIT2D(int _h, int _w) : h(_h), w(_w), data(_h + 1, vector<T>(_w + 1, 0)) {}
  
  void add(int a, int b, T v) {
    assert(0 <= a && a < h);
    assert(0 <= b && b < w);
    a++;
    b++;
    for(int y = a; y <= h; y += y & -y){
      for(int x = b; x <= w; x += x & -x){
        data[y - 1][x - 1] += v;
      }
    }
  }
  
  
  T sum(int a, int b) {
    T s = 0;
    for(int y = a; y > 0; y -= y & -y){
      for(int x = b; x > 0; x -= x & -x){
        s += data[y - 1][x - 1];
      }
    }
    return s;
  }
  
  T sum(int h1, int w1, int h2, int w2) {
    assert(0 <= h1 && h1 < h);
    assert(0 <= w1 && w1 < w);
    assert(0 < h2 && h2 <= h);
    assert(0 < w2 && w2 <= w);
    assert(h1 < h2);
    assert(w1 < w2);
    return sum(h2, w2) - sum(h2, w1) - sum(h1, w2) + sum(h1, w1);
  }
};
int main() {
  int H, W, T, Q; cin >> H >> W >> T >> Q;
  BIT2D<int> fin(H, W), mada(H, W);
  queue<array<int, 3>> que;
  for (int query = 0; query < Q; ++query) {
    int t, c, h, w; cin >> t >> c >> h >> w;
    h--; w--;
    while (!que.empty()) {
      array<int, 3> a = que.front();
      if (a[0] > t) break;
      que.pop();
      int x = a[1], y = a[2];
      mada.add(x, y, -1);
      fin.add(x, y, 1);
    }
    if (c == 0) {
      mada.add(h, w, 1);
      que.push({t+T, h, w});
    }
    else if (c == 1) {
      if (fin.sum(h, w, h+1, w+1) == 1) fin.add(h, w, -1);
    }
    else {
      int h2, w2; cin >> h2 >> w2;
      h2--; w2--;
      cout << fin.sum(h, w, h2+1, w2+1) << " " << mada.sum(h, w, h2+1, w2+1) << endl;
    }
  }
}
accuracy: 1
time_ms: 210
memory_kb: 35680
final_rank: 6