(线段树两个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 }

 

posted @ 2017-06-09 00:06  tak_fate  阅读(204)  评论(0编辑  收藏  举报