比较综合的一道题目。
二维的线段树,支持区间的add和set操作,然后询问子矩阵的sum,min,max
写完这道题也是醉醉哒,代码仓库里还有一份代码就是在query的过程中也pushdown向下传递标记。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 6 const int maxnode = 1 << 17; 7 int _sum, _min, _max, op, x1, x2, y1, y2, x, v; 8 9 struct IntervalTree 10 { 11 int maxv[maxnode], minv[maxnode], sumv[maxnode], setv[maxnode], addv[maxnode]; 12 13 void maintain(int o, int L, int R) 14 { 15 int lc = o*2, rc = o*2+1; 16 if(R > L) 17 { 18 sumv[o] = sumv[lc] + sumv[rc]; 19 minv[o] = min(minv[lc], minv[rc]); 20 maxv[o] = max(maxv[lc], maxv[rc]); 21 } 22 if(setv[o] >= 0) { maxv[o] = minv[o] = setv[o]; sumv[o] = (R-L+1)*setv[o]; } 23 if(addv[o]) { minv[o] += addv[o]; maxv[o] += addv[o]; sumv[o] += (R-L+1)*addv[o]; } 24 } 25 26 void pushdown(int o) 27 { 28 int lc = o*2, rc = o*2+1; 29 if(setv[o] >= 0) 30 { 31 setv[lc] = setv[rc] = setv[o]; 32 addv[lc] = addv[rc] = 0; 33 setv[o] = -1; 34 } 35 if(addv[o]) 36 { 37 addv[lc] += addv[o]; 38 addv[rc] += addv[o]; 39 addv[o] = 0; 40 } 41 } 42 43 void update(int o, int L, int R) 44 { 45 int lc = o*2, rc = o*2+1; 46 if(y1 <= L && R <= y2) 47 { 48 if(op == 1) addv[o] += v; 49 else { setv[o] = v; addv[o] = 0; } 50 } 51 else 52 { 53 pushdown(o); //往下传递标记 54 int M = (L + R) / 2; 55 if(y1 <= M) update(lc, L, M); else maintain(lc, L, M); 56 if(y2 > M) update(rc, M+1, R); else maintain(rc, M+1, R); 57 } 58 maintain(o, L, R); 59 } 60 61 void query(int o, int L, int R, int add) 62 { 63 if(setv[o] >= 0) 64 { 65 int v = setv[o] + addv[o] + add; 66 _sum += v * (min(y2, R) - max(y1, L) + 1); 67 _min = min(_min, v); 68 _max = max(_max, v); 69 } 70 else if(y1 <= L && R <= y2) 71 { 72 _sum += sumv[o] + add*(R-L+1); 73 _min = min(_min, minv[o] + add); 74 _max = max(_max, maxv[o] + add); 75 } 76 else 77 { 78 int M = (L + R) / 2; 79 if(y1 <= M) query(o*2, L, M, add + addv[o]); 80 if(y2 > M) query(o*2+1, M+1, R, add + addv[o]); 81 } 82 } 83 }; 84 85 const int maxr = 20 + 5; 86 const int INF = 1000000000; 87 88 IntervalTree tree[maxr]; 89 90 int main() 91 { 92 //freopen("in.txt", "r", stdin); 93 94 int r, c, m; 95 while(scanf("%d%d%d", &r, &c, &m) == 3) 96 { 97 memset(tree, 0, sizeof(tree)); 98 for(int x = 1; x <= r; x++) 99 { 100 memset(tree[x].setv, -1, sizeof(tree[x].setv)); 101 tree[x].setv[1] = 0; 102 } 103 104 while(m--) 105 { 106 scanf("%d%d%d%d%d", &op, &x1, &y1, &x2, &y2); 107 if(op < 3) 108 { 109 scanf("%d", &v); 110 for(x = x1; x <= x2; x++) tree[x].update(1, 1, c); 111 } 112 else 113 { 114 _sum = 0; _max = -INF; _min = INF; 115 for(x = x1; x <= x2; x++) tree[x].query(1, 1, c, 0); 116 printf("%d %d %d\n", _sum, _min, _max); 117 } 118 } 119 } 120 121 return 0; 122 }