UVA - 11992 —— Fast Matrix Operations 【二维线段树转一维】
http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=18697
#include <cstdio> #include <iostream> #include <cstring> #include <string> #define INF 0x3f3f3f3f #define left rt<<1 #define right rt<<1|1 using namespace std; const int MAXN = 1048576 + 5; struct Node { int sum, min, max; Node() {} Node(int sum, int min, int max):sum(sum), min(min), max(max) {} }; struct Tree { Node a[MAXN<<1]; int set[MAXN<<1]; int add[MAXN<<1]; } tree[20]; int r, c; void pushup(int i, int rt) { Node* cur = tree[i].a; cur[rt].sum = cur[left].sum + cur[right].sum; cur[rt].max = max(cur[left].max, cur[right].max); cur[rt].min = min(cur[left].min, cur[right].min); } void pushdown(int i, int rt, int w) { Tree &cur = tree[i];
// 优先set,其次add if(cur.set[rt] != -1) { cur.set[left] = cur.set[right] = cur.set[rt]; cur.a[left].sum = (w - (w>>1)) * cur.set[rt]; cur.a[right].sum = (w>>1) * cur.set[rt]; cur.a[left].min = cur.a[right].min = cur.a[left].max = cur.a[right].max = cur.set[rt]; cur.add[left] = cur.add[right] = 0; cur.set[rt] = -1; } if(cur.add[rt] != 0) { cur.add[left] += cur.add[rt]; cur.add[right] += cur.add[rt]; cur.a[left].sum += (w - (w>>1)) * cur.add[rt]; cur.a[right].sum += (w>>1) * cur.add[rt]; cur.a[left].min += cur.add[rt]; cur.a[right].min += cur.add[rt]; cur.a[left].max += cur.add[rt]; cur.a[right].max += cur.add[rt]; cur.add[rt] = 0; } } void add(int ql, int qr, int x, int i, int rt, int l, int r) { // printf("%d %d %d\n", rt, l, r); // if(ql <= l && r <= qr) { tree[i].add[rt] += x; tree[i].a[rt].sum += (r - l + 1) * x; tree[i].a[rt].max += x; tree[i].a[rt].min += x; return; } pushdown(i, rt, r - l + 1); int m = (l + r) >> 1; if(ql <= m) add(ql, qr, x, i, left, l, m); if(qr > m) add(ql, qr, x, i, right, m+1, r); pushup(i, rt); } void set(int ql, int qr, int x, int i, int rt, int l, int r) { if(ql <= l && r <= qr) { tree[i].set[rt] = x; tree[i].a[rt].sum = (r - l + 1) * x; tree[i].a[rt].max = tree[i].a[rt].min = x; tree[i].add[rt] = 0; return; } pushdown(i, rt, r - l + 1); int m = (l + r) >> 1; if(ql <= m) set(ql, qr, x, i, left, l, m); if(qr > m) set(ql, qr, x, i, right, m+1, r); pushup(i, rt); } Node query(int ql, int qr, int i, int rt, int l, int r) { if(ql <= l && r <= qr) { Node &cur = tree[i].a[rt]; return Node(cur.sum, cur.min, cur.max); } pushdown(i, rt, r - l + 1); int m = (l + r) >> 1; Node ret(0, INF, -1), temp; if(ql <= m) { temp = query(ql, qr, i, left, l, m); ret.sum += temp.sum; ret.max = max(ret.max, temp.max); ret.min = min(ret.min, temp.min); } if(qr > m) { temp = query(ql, qr, i, right, m+1, r); ret.sum += temp.sum; ret.max = max(ret.max, temp.max); ret.min = min(ret.min, temp.min); } return ret; } void build(int i, int rt, int l, int r) { tree[i].add[rt] = 0; tree[i].set[rt] = -1; if(l == r) { tree[i].a[rt].sum = tree[i].a[rt].min = tree[i].a[rt].max = 0; return; } int m = (l + r) >> 1; build(i, left, l, m); build(i, right, m+1, r); pushup(i, rt); } int main () { int m, type, x1, y1, x2, y2, v; while(scanf("%d%d%d", &r, &c, &m) != EOF) { for(int i=0; i<r; i++) { build(i, 1, 1, c); } while(m--) { scanf("%d%d%d%d%d", &type, &x1, &y1, &x2, &y2); x1--; x2--; if(type == 1) { scanf("%d", &v); for(int i=x1; i<=x2; i++) { add(y1, y2, v, i, 1, 1, c); } } else if(type == 2) { scanf("%d", &v); for(int i=x1; i<=x2; i++) { set(y1, y2, v, i, 1, 1, c); } } else { Node ans(0, INF, -1), temp; for(int i=x1; i<=x2; i++) { temp = query(y1, y2, i, 1, 1, c); ans.sum += temp.sum; ans.max = max(ans.max, temp.max); ans.min = min(ans.min, temp.min); } printf("%d %d %d\n", ans.sum, ans.min, ans.max); } } } return 0; }