(线段树两个lazy标记需要设定优先级)UVA 11992 - Fast Matrix Operations
题意:
一个n*m的矩阵,最多20行,元素总数量不超过1000000,三种操作,子矩阵+v,子矩阵=v,还有查询子矩阵的(最大值,最小值,和)。
分析:
显然需要懒惰标记,而且需要两个,一个lazy表示赋值的标记,一个add表示增加的标记。
而且需要优先级,显然赋值的优先级比增加高。
因为如果节点上有add,但是这时候lazy的标记push_down下来,显然过去的已经全都作废。
而如果节点上有lazy,但是这个时候add的标记push_down下来,显然lazy标记依然有效,并且需要加上新的add标记。
代码:
1 #include <queue> 2 #include <string> 3 #include <cstdio> 4 #include <cstring> 5 #include <iostream> 6 #include <algorithm> 7 #include <map> 8 #include <cmath> 9 10 11 using namespace std; 12 13 typedef long long ll; 14 typedef unsigned long long ull; 15 typedef pair<int, int> pii; 16 typedef pair<ull, ull> puu; 17 18 #define inf (0x3f3f3f3f) 19 #define lnf (0x3f3f3f3f3f3f3f3f) 20 #define eps (1e-8) 21 #define fi first 22 #define se second 23 24 //-------------------------- 25 26 const ll mod = 1000000007; 27 const int maxn = 1000010; 28 29 struct Node { 30 int left, right; 31 int sum; 32 int maxs, mins; 33 int lazy; 34 int add; 35 } node[maxn << 2]; 36 int n, m, q; 37 38 void build(int n, int left, int right) { 39 node[n].left = left; 40 node[n].right = right; 41 node[n].sum = node[n].maxs = node[n].mins = 0; 42 node[n].lazy = -1; 43 node[n].add = 0; 44 if(left == right)return ; 45 int mid = (left + right) >> 1; 46 build(n << 1, left, mid); 47 build(n << 1 | 1, mid + 1, right); 48 } 49 50 void push_up(int n) { 51 node[n].sum = node[n << 1].sum + node[n << 1 | 1].sum; 52 node[n].mins = min(node[n << 1].mins, node[n << 1 | 1].mins); 53 node[n].maxs = max(node[n << 1].maxs, node[n << 1 | 1].maxs); 54 } 55 56 void push_down(int n) { 57 if(node[n].lazy != -1) { 58 node[n << 1].lazy = node[n << 1 | 1].lazy = node[n].lazy; 59 node[n << 1].add = node[n << 1 | 1].add = 0; 60 node[n << 1].sum = node[n].lazy * (node[n << 1].right - node[n << 1].left + 1); 61 node[n << 1 | 1].sum = node[n].lazy * (node[n << 1 | 1].right - node[n << 1 | 1].left + 1); 62 node[n << 1].mins = node[n << 1].maxs = node[n].lazy; 63 node[n << 1 | 1].mins = node[n << 1 | 1].maxs = node[n].lazy; 64 node[n].lazy = -1; 65 } 66 if(node[n].add != 0) { 67 node[n << 1].add += node[n].add; 68 node[n << 1 | 1].add += node[n].add; 69 node[n << 1].sum += node[n].add * (node[n << 1].right - node[n << 1].left + 1); 70 node[n << 1 | 1].sum += node[n].add * (node[n << 1 | 1].right - node[n << 1 | 1].left + 1); 71 node[n << 1].maxs += node[n].add; 72 node[n << 1].mins += node[n].add; 73 node[n << 1 | 1].maxs += node[n].add; 74 node[n << 1 | 1].mins += node[n].add; 75 node[n].add = 0; 76 } 77 } 78 79 void Set(int n, int left, int right, int val) { 80 if(node[n].left >= left && node[n].right <= right) { 81 node[n].lazy = val; 82 node[n].sum = val * (node[n].right - node[n].left + 1); 83 node[n].mins = val; 84 node[n].maxs = val; 85 node[n].add = 0; 86 return ; 87 } 88 push_down(n); 89 int mid = (node[n].left + node[n].right) >> 1; 90 if(mid >= left)Set(n << 1, left, right, val); 91 if(mid < right)Set(n << 1 | 1, left, right, val); 92 push_up(n); 93 } 94 95 void Add(int n, int left, int right, int val) { 96 if(node[n].left >= left && node[n].right <= right) { 97 node[n].add += val; 98 node[n].sum += val * (node[n].right - node[n].left + 1); 99 node[n].mins += val; 100 node[n].maxs += val; 101 return ; 102 } 103 push_down(n); 104 int mid = (node[n].left + node[n].right) >> 1; 105 if(mid >= left)Add(n << 1, left, right, val); 106 if(mid < right)Add(n << 1 | 1, left, right, val); 107 push_up(n); 108 109 } 110 111 112 int query_sum(int n, int left, int right) { 113 if(node[n].left >= left && node[n].right <= right) { 114 return node[n].sum; 115 } 116 push_down(n); 117 int mid = (node[n].left + node[n].right) >> 1; 118 int sum = 0; 119 if(mid >= left)sum += query_sum(n << 1, left, right); 120 if(mid < right)sum += query_sum(n << 1 | 1, left, right); 121 push_up(n); 122 return sum; 123 } 124 int query_max(int n, int left, int right) { 125 if(node[n].left >= left && node[n].right <= right) { 126 return node[n].maxs; 127 } 128 push_down(n); 129 int mid = (node[n].left + node[n].right) >> 1; 130 int res = -inf; 131 if(mid >= left)res = max(res, query_max(n << 1, left, right)); 132 if(mid < right)res = max(res, query_max(n << 1 | 1, left, right)); 133 push_up(n); 134 return res; 135 } 136 137 int query_min(int n, int left, int right) { 138 if(node[n].left >= left && node[n].right <= right) { 139 return node[n].mins; 140 } 141 push_down(n); 142 int mid = (node[n].left + node[n].right) >> 1; 143 int res = inf; 144 if(mid >= left)res = min(res, query_min(n << 1, left, right)); 145 if(mid < right)res = min(res, query_min(n << 1 | 1, left, right)); 146 push_up(n); 147 return res; 148 } 149 150 void solve() { 151 while(~scanf("%d%d%d", &n, &m, &q)) { 152 build(1, 1, n * m); 153 int op, x1, x2, y1, y2, val; 154 int c = 0; 155 while(q--) { 156 scanf("%d%d%d%d%d", &op, &x1, &y1, &x2, &y2); 157 if(op == 1) { 158 scanf("%d", &val); 159 for(int i = x1; i <= x2; i++) { 160 Add(1, (i - 1)*m + y1, (i - 1)*m + y2, val); 161 } 162 } else if(op == 2) { 163 scanf("%d", &val); 164 for(int i = x1; i <= x2; i++) { 165 Set(1, (i - 1)*m + y1, (i - 1)*m + y2, val); 166 } 167 } else { 168 int a = 0, b = inf, c = -inf; 169 for(int i = x1; i <= x2; i++) { 170 a += query_sum(1, (i - 1) * m + y1, (i - 1) * m + y2); 171 b = min(b, query_min(1, (i - 1) * m + y1, (i - 1) * m + y2)); 172 c = max(c, query_max(1, (i - 1) * m + y1, (i - 1) * m + y2)); 173 } 174 printf("%d %d %d\n", a, b, c); 175 } 176 } 177 } 178 179 } 180 181 int main() { 182 #ifndef ONLINE_JUDGE 183 freopen("1.in", "r", stdin); 184 // freopen("1.out", "w", stdout); 185 #endif 186 solve(); 187 return 0; 188 }