題意:有一個行r,列c的矩陣的初始值都為0,然後有三種操作,子矩陣(x1,y1,x2,y2)全部元素都增加v或置為v,或者查詢這個子矩陣的元素和、最大值、最小值。
題解:區間修改模板題,把每行當做一個線段樹。
#include#include #include using namespace std; const int N = 50000 * 4; const int INF = 0x3f3f3f3f; int r, c, q, op, x1, x2, y1, y2, v; int summ, minn, maxx; struct Node { int sum[N], mi[N], ma[N], addv[N], setv[N]; void pushup(int k, int left, int right) { int lc = k * 2, rc = k * 2 + 1; if (right > left) { sum[k] = sum[lc] + sum[rc]; mi[k] = min(mi[lc], mi[rc]); ma[k] = max(ma[lc], ma[rc]); } if (setv[k] >= 0) { mi[k] = ma[k] = setv[k]; sum[k] = setv[k] * (right - left + 1); } if (addv[k]) { mi[k] += addv[k]; ma[k] += addv[k]; sum[k] += addv[k] * (right - left + 1); } } void pushdown(int k) { int lc = k * 2, rc = k * 2 + 1; if (setv[k] >= 0) { setv[lc] = setv[rc] = setv[k]; addv[lc] = addv[rc] = 0; setv[k] = -1; } if (addv[k]) { addv[lc] += addv[k]; addv[rc] += addv[k]; addv[k] = 0; } } void update(int k, int left, int right) { int lc = k * 2, rc = k * 2 + 1; if (y1 <= left && right <= y2) { if (op == 1) addv[k] += v; else { setv[k] = v; addv[k] = 0; } } else { pushdown(k); int mid = (left + right) / 2; if (y1 <= mid) update(lc, left, mid); else pushup(lc, left, mid); if (mid < y2) update(rc, mid + 1, right); else pushup(rc, mid + 1, right); } pushup(k, left, right); } void query(int k, int left, int right, int add) { if (setv[k] >= 0) { int v = setv[k] + add + addv[k]; summ += v * (min(right, y2) - max(left, y1) + 1); minn = min(minn, v); maxx = max(maxx, v); } else if (y1 <= left && right <= y2) { summ += sum[k] + add * (right - left + 1); minn = min(minn, mi[k] + add); maxx = max(maxx, ma[k] + add); } else { int mid = (left + right) / 2; if (y1 <= mid) query(k * 2, left, mid, add + addv[k]); if (y2 > mid) query(k * 2 + 1, mid + 1, right, add + addv[k]); } } }node[22]; void init() { for (int i = 1; i <= r; i++) { memset(node[i].sum, 0, sizeof(node[i].sum)); memset(node[i].mi, 0, sizeof(node[i].mi)); memset(node[i].ma, 0, sizeof(node[i].ma)); memset(node[i].addv, 0, sizeof(node[i].addv)); memset(node[i].setv, -1, sizeof(node[i].setv)); node[i].setv[1] = 0; } } int main() { while (scanf("%d%d%d", &r, &c, &q) == 3) { init(); while (q--) { scanf("%d%d%d%d%d", &op, &x1, &y1, &x2, &y2); if (op < 3) { scanf("%d", &v); for (int i = x1; i <= x2; i++) node[i].update(1, 1, c); } else { summ = 0, minn = INF, maxx = -INF; for (int i = x1; i <= x2; i++) node[i].query(1, 1, c, 0); printf("%d %d %d\n", summ, minn, maxx); } } } return 0; }