UVA_11192
如果是在一维的序列上进行这些操作的话,那么线段树就可以了。不过现在题目将这些操作拓展到了二维,回想线段树的本质是二分线段,那么对于一个二维的矩阵,拓展一下就应当是四分矩阵了。
#include<stdio.h> #include<string.h> #include<algorithm> #define MAXD 1000010 #define INF 0x3f3f3f3f int N, M, P, node; struct SegTree { int x1, y1, x2, y2, sum, min, max, add, to, son[4], area; void pushdown(); void update(); void init() { sum = add = to = 0; son[0] = son[1] = son[2] = son[3] = 0; min = INF, max = -INF; } }st[4 * MAXD]; inline void To(int cur, int v) { if(cur) { st[cur].to = v, st[cur].add = 0; st[cur].min = st[cur].max = v, st[cur].sum = v * st[cur].area; } } inline void Add(int cur, int v) { if(cur) { st[cur].add += v; st[cur].min += v, st[cur].max += v, st[cur].sum += v * st[cur].area; } } inline void SegTree::pushdown() { if(to) { for(int i = 0; i < 4; i ++) To(son[i], to); to = 0; } if(add) { for(int i = 0; i < 4; i ++) Add(son[i], add); add = 0; } } inline void SegTree::update() { min = INF, max = -INF, sum = 0; for(int i = 0; i < 4; i ++) { sum += st[son[i]].sum; min = std::min(min, st[son[i]].min); max = std::max(max, st[son[i]].max); } } void build(int cur, int x1, int x2, int y1, int y2) { int midx = x1 + x2 >> 1, midy = y1 + y2 >> 1; st[cur].init(), st[cur].sum = st[cur].min = st[cur].max = 0; st[cur].x1 = x1, st[cur].x2 = x2, st[cur].y1 = y1, st[cur].y2 = y2, st[cur].area = (x2 - x1 + 1) * (y2 - y1 + 1); if(x1 == x2 && y1 == y2) return ; st[cur].son[0] = ++ node, build(node, x1, midx, y1, midy); if(midx < x2) st[cur].son[1] = ++ node, build(node, midx + 1, x2, y1, midy); if(midx < x2 && midy < y2) st[cur].son[2] = ++ node, build(node, midx + 1, x2, midy + 1, y2); if(midy < y2) st[cur].son[3] = ++ node, build(node, x1, midx, midy + 1, y2); st[cur].update(); } void init() { st[0].init(), node = 1; build(1, 1, N, 1, M); } inline int inside(int k, int x1, int x2, int y1, int y2) { return st[k].x1 >= x1 && st[k].x2 <= x2 && st[k].y1 >= y1 && st[k].y2 <= y2; } inline int inter(int k, int x1, int x2, int y1, int y2) { if(st[k].x2 < x1 || st[k].x1 > x2 || st[k].y2 < y1 || st[k].y1 > y2) return 0; return 1; } void refresh(int cur, int x1, int x2, int y1, int y2, int v, int op) { if(inside(cur, x1, x2, y1, y2)) { if(op == 1) Add(cur, v); else To(cur, v); return ; } st[cur].pushdown(); for(int i = 0; i < 4; i ++) if(st[cur].son[i] && inter(st[cur].son[i], x1, x2, y1, y2)) refresh(st[cur].son[i], x1, x2, y1, y2, v, op); st[cur].update(); } void query(int cur, int x1, int x2, int y1, int y2, int &sum, int &min, int &max) { if(inside(cur, x1, x2, y1, y2)) { sum += st[cur].sum, min = std::min(min, st[cur].min), max = std::max(max, st[cur].max); return ; } st[cur].pushdown(); for(int i = 0; i < 4; i ++) if(st[cur].son[i] && inter(st[cur].son[i], x1, x2, y1, y2)) query(st[cur].son[i], x1, x2, y1, y2, sum, min, max); } void solve() { int i, op, x1, y1, x2, y2, v, min, max, sum; for(i = 0; i < P; i ++) { scanf("%d%d%d%d%d", &op, &x1, &y1, &x2, &y2); if(op == 3) { min = INF, max = -INF, sum = 0; query(1, x1, x2, y1, y2, sum, min, max); printf("%d %d %d\n", sum, min, max); } else { scanf("%d", &v); refresh(1, x1, x2, y1, y2, v, op); } } } int main() { while(scanf("%d%d%d", &N, &M, &P) == 3) { init(); solve(); } return 0; }