#include <iostream>
#include <vector>
#define MAXN 1005
using namespace std;
struct SegmentTree2D {
int n, m;
vector<vector<int>> tree;
vector<vector<int>> lazyAdd;
vector<vector<int>> lazyMul;
SegmentTree2D(int _n, int _m) : n(_n), m(_m) {
tree.resize(4 * n, vector<int>(4 * m, 0));
lazyAdd.resize(4 * n, vector<int>(4 * m, 0));
lazyMul.resize(4 * n, vector<int>(4 * m, 1));
}
void pushDown(int x, int y, int lx, int rx, int ly, int ry) {
if (lx == rx && ly == ry) return;
int midX = (lx + rx) / 2, midY = (ly + ry) / 2;
int l = x*2 + 1, r = x*2 + 2, u = y*2 + 1, v = y*2 + 2;
// Propagate Lazy Multiplication
if (lazyMul[x][y] != 1) {
applyMul(l, y, lx, midX, ly, ry, lazyMul[x][y]);
applyMul(r, y, midX + 1, rx, ly, ry, lazyMul[x][y]);
applyMul(x, u, lx, rx, ly, midY, lazyMul[x][y]);
applyMul(x, v, lx, rx, midY + 1, ry, lazyMul[x][y]);
lazyMul[x][y] = 1;
}
// Propagate Lazy Addition
if (lazyAdd[x][y] != 0) {
applyAdd(l, y, lx, midX, ly, ry, lazyAdd[x][y]);
applyAdd(r, y, midX + 1, rx, ly, ry, lazyAdd[x][y]);
applyAdd(x, u, lx, rx, ly, midY, lazyAdd[x][y]);
applyAdd(x, v, lx, rx, midY + 1, ry, lazyAdd[x][y]);
lazyAdd[x][y] = 0;
}
}
void applyAdd(int x, int y, int lx, int rx, int ly, int ry, int val) {
tree[x][y] += val * (rx - lx + 1) * (ry - ly + 1);
if (lx != rx || ly != ry) {
lazyAdd[x][y] += val;
}
}
void applyMul(int x, int y, int lx, int rx, int ly, int ry, int val) {
tree[x][y] *= val;
if (lx != rx || ly != ry) {
lazyMul[x][y] *= val;
lazyAdd[x][y] *= val;
}
}
void update(int x1, int y1, int x2, int y2, int val, bool isAdd, int x, int lx, int rx, int y, int ly, int ry) {
if (x1 > rx || x2 < lx || y1 > ry || y2 < ly) return;
if (x1 <= lx && rx <= x2 && y1 <= ly && ry <= y2) {
if (isAdd)
applyAdd(x, y, lx, rx, ly, ry, val);
else
applyMul(x, y, lx, rx, ly, ry, val);
return;
}
pushDown(x, y, lx, rx, ly, ry);
int midX = (lx + rx) / 2, midY = (ly + ry) / 2;
update(x1, y1, x2, y2, val, isAdd, x*2+1, lx, midX, y, ly, ry);
update(x1, y1, x2, y2, val, isAdd, x*2+2, midX+1, rx, y, ly, ry);
update(x1, y1, x2, y2, val, isAdd, x, lx, rx, y*2+1, ly, midY);
update(x1, y1, x2, y2, val, isAdd, x, lx, rx, y*2+2, midY+1, ry);
tree[x][y] = tree[x*2+1][y] + tree[x*2+2][y] + tree[x][y*2+1] + tree[x][y*2+2];
}
int query(int x1, int y1, int x2, int y2, int x, int lx, int rx, int y, int ly, int ry) {
if (x1 > rx || x2 < lx || y1 > ry || y2 < ly) return 0;
if (x1 <= lx && rx <= x2 && y1 <= ly && ry <= y2) return tree[x][y];
pushDown(x, y, lx, rx, ly, ry);
int midX = (lx + rx) / 2, midY = (ly + ry) / 2;
return query(x1, y1, x2, y2, x*2+1, lx, midX, y, ly, ry) +
query(x1, y1, x2, y2, x*2+2, midX+1, rx, y, ly, ry) +
query(x1, y1, x2, y2, x, lx, rx, y*2+1, ly, midY) +
query(x1, y1, x2, y2, x, lx, rx, y*2+2, midY+1, ry);
}
};
int main() {
int n = 5, m = 5; // Example dimensions
SegmentTree2D st(n, m);
st.update(1, 1, 3, 3, 5, true, 0, 0, n-1, 0, 0, m-1); // Add 5 to submatrix (1,1) to (3,3)
cout << st.query(1, 1, 3, 3, 0, 0, n-1, 0, 0, m-1) << endl; // Query sum of submatrix (1,1) to (3,3)
return 0;
}