UVA 11992 ——线段树(区间修改)
解题思路:
将矩阵每一行建立一棵线段树,进而变成一维问题求解。注意数组要开 4*N
代码如下:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 6 using namespace std; 7 const int maxn = 1000000 + 10; 8 9 const int INF = 2000000000; 10 int q, x1_, x2_, y1, y2, v_add, v_set; 11 12 struct segment_tree { 13 int sumv[4*maxn],minv[4*maxn],maxv[4*maxn]; 14 int addv[4*maxn], setv[4*maxn]; 15 void maintain(int o, int L, int R) { 16 int lc = 2*o, rc = 2*o + 1; 17 sumv[o] = minv[o] = maxv[o] = 0; 18 if(setv[o] >= 0) { 19 sumv[o] = setv[o] * (R-L+1); 20 minv[o] = maxv[o] = setv[o]; 21 } 22 else if(R > L) { 23 sumv[o] = sumv[lc] + sumv[rc]; 24 minv[o] = min(minv[lc], minv[rc]); 25 maxv[o] = max(maxv[lc], maxv[rc]); 26 } 27 minv[o] += addv[o]; maxv[o] += addv[o]; sumv[o] += addv[o] * (R-L+1); 28 } 29 void pushdown(int o) { 30 int lc = 2*o, rc = 2*o+1; 31 if(setv[o] >= 0) { 32 setv[lc] = setv[rc] = setv[o]; 33 addv[lc] = addv[rc] = 0; 34 setv[o] = -1; 35 } 36 if(addv[o] > 0) { 37 addv[lc] += addv[o]; 38 addv[rc] += addv[o]; 39 addv[o] = 0; 40 } 41 } 42 void update_add(int o, int L, int R) { 43 int lc = 2*o, rc = o*2+1; 44 if(y1 <= L && y2 >= R) { 45 addv[o] += v_add; 46 } 47 else { 48 pushdown(o); 49 int M = L + (R-L)/2; 50 if(y1 <= M) update_add(lc, L, M); else maintain(lc, L, M); 51 if(y2 > M) update_add(rc, M+1, R);else maintain(rc, M+1, R); 52 } 53 maintain(o, L, R); 54 } 55 void update_set(int o, int L, int R) { 56 int lc = 2*o, rc = o*2+1; 57 if(y1 <= L && y2 >= R) { 58 setv[o] = v_set; 59 addv[o] = 0; 60 } 61 else { 62 pushdown(o); 63 int M = L + (R-L)/2; 64 if(y1 <= M) update_set(lc, L, M); else maintain(lc, L, M); 65 if(y2 > M) update_set(rc, M+1, R); else maintain(rc, M+1, R); 66 } 67 maintain(o, L, R); 68 } 69 70 void query(int o, int L, int R, int add, int& _min, int& _max, int& _sum) { 71 if(setv[o] >= 0) { 72 _sum += (add+setv[o]+addv[o]) * (min(R, y2)-max(L, y1)+1); 73 _min = min(_min, setv[o]+addv[o]+add); 74 _max = max(_max, setv[o]+addv[o]+add); 75 } 76 else if(y1 <= L && y2 >= R) { 77 _sum += sumv[o] + add * (R-L+1); 78 _min = min(_min, minv[o]+add); 79 _max = max(_max, maxv[o]+add); 80 } 81 else { 82 int M = L + (R-L)/2; 83 if(y1 <= M) query(o*2, L, M, add+addv[o], _min, _max, _sum); 84 if(y2 > M) query(o*2+1, M+1, R, add+addv[o], _min, _max, _sum); 85 } 86 } 87 88 void init() { 89 memset(setv, -1, sizeof setv); 90 memset(addv, 0, sizeof addv); 91 memset(sumv, 0, sizeof sumv); 92 memset(minv, 0, sizeof minv); 93 memset(maxv, 0, sizeof maxv); 94 } 95 }; 96 int r, c, m; 97 const int maxr = 20 + 5; 98 99 segment_tree tree[maxr]; 100 101 int main(int argc, const char * argv[]) { 102 103 while(scanf("%d%d%d", &r, &c, &m) == 3){ 104 105 for(int i = 0; i < maxr; i++) tree[i].init(); 106 for(int i = 0; i < m; i++) { 107 108 scanf("%d%d%d%d%d", &q, &x1_, &y1, &x2_, &y2); 109 if(q == 1){ 110 scanf("%d", &v_add); 111 for(int x = x1_; x <= x2_; x++) { 112 tree[x].update_add(1, 1, c); 113 } 114 } 115 if(q == 2) { 116 scanf("%d", &v_set); 117 for(int x = x1_; x <= x2_; x++) { 118 tree[x].update_set(1, 1, c); 119 } 120 } 121 if(q == 3){ 122 int gmin = INF, gmax = -INF, gsum = 0; 123 for(int x = x1_; x <= x2_; x++) { 124 int _min = INF, _max = -INF, _sum = 0; 125 tree[x].query(1, 1, c, 0,_min, _max, _sum); 126 gsum += _sum; 127 gmin = min(gmin, _min); 128 gmax = max(gmax, _max); 129 } 130 printf("%d %d %d\n", gsum, gmin, gmax); 131 } 132 } 133 } 134 return 0; 135 }