给你一个矩阵,然后有3种操作:
1 x1 y1 x2 y2 val 是将矩阵x1 y1 x2 y2的区间内的值全部增加val
2 x1 y1 x2 y2 val 是将矩阵x1 y1 x2 y2的区间内的值全部设置为val
3 x1 y1 x2 y2 求出 x1 y1 x2 y2的区间内的和,最大值,最小值。
这个题是一道线段树题,要求进行区间修改设置以及求和。
由于r <= 20,r*c <= 1e6,所以我们可以将矩阵展开成一维,每次询问进行(x2-x1)次查询操作即可。这样就转换成了线段树问题。
我们做addv标记加val操作,用setv标记变val操作;若遇到setv,我们需要清空addv,反之则不需要。若在操作的时候setv和addv都存在,那么先执行setv操作,之后执行addv操作。
AC代码
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ls o*2
#define rs o*2+1
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int N = (1e6+5)*4;
int sumv[N], minv[N], maxv[N];
int addv[N], setv[N];
int ql, qr, val;
int x1, y1, x2, y2;
int _sum, _max, _min;
inline void maintain(int o) {
sumv[o] = sumv[ls] + sumv[rs];
minv[o] = min(minv[ls], minv[rs]);
maxv[o] = max(maxv[ls], maxv[rs]);
}
void build(int o, int L, int R) {
if(L == R) {
sumv[o] = minv[o] = maxv[o] = 0;
addv[o] = setv[o] = 0;
return ;
}
int M = (L+R)/2;
build(ls, L, M);
build(rs, M+1, R);
maintain(o);
}
void pushdown(int o, int L, int R) {
int M = (L+R)/2;
if(setv[o]) {
setv[ls] = setv[rs] = setv[o];
addv[ls] = addv[rs] = 0;
sumv[ls] = (M-L+1)*setv[o], sumv[rs] = (R-M)*setv[o];
minv[ls] = minv[rs] = setv[o];
maxv[ls] = maxv[rs] = setv[o];
setv[o] = 0;
}
if(addv[o]) {
addv[ls] += addv[o], addv[rs] += addv[o];
sumv[ls] += (M-L+1) * addv[o], sumv[rs] += (R-M) * addv[o];
minv[ls] += addv[o], minv[rs] += addv[o];
maxv[ls] += addv[o], maxv[rs] += addv[o];
addv[o] = 0;
}
}
void add(int o, int L, int R) {
if(ql <= L && R <= qr) {
addv[o] += val;
sumv[o] += (R-L+1) * val;
minv[o] += val;
maxv[o] += val;
return ;
}
pushdown(o, L, R);
int M = (L+R)/2;
if(ql <= M) add(ls, L, M);
if(qr > M) add(rs, M+1, R);
maintain(o);
}
void set(int o, int L, int R) {
if(ql <= L && R <= qr) {
setv[o] = val;
sumv[o] = (R-L+1) * val;
minv[o] = maxv[o] = val;
addv[o] = 0;
return ;
}
pushdown(o, L, R);
int M = (L+R)/2;
if(ql <= M) set(ls, L, M);
if(qr > M) set(rs, M+1, R);
maintain(o);
}
void query(int o, int L, int R) {
if(ql <= L && R <= qr) {
_sum += sumv[o];
_min = min(_min, minv[o]);
_max = max(_max, maxv[o]);
return ;
}
pushdown(o, L, R);
int M = (L+R)/2;
if(ql <= M) query(ls, L, M);
if(qr > M) query(rs, M+1, R);
}
int main() {
int r, c, q, ch;
int n;
while(scanf("%d%d%d", &r, &c, &q) != EOF) {
n = r*c;
build(1, 1, n);
while(q--) {
scanf("%d%d%d%d%d", &ch, &x1, &y1, &x2, &y2);
switch(ch) {
case 1:
scanf("%d", &val);
for(int i = x1; i <= x2; i++) {
ql = (i-1)*c + y1;
qr = (i-1)*c + y2;
add(1, 1, n);
}
break;
case 2:
scanf("%d", &val);
for(int i = x1; i <= x2; i++) {
ql = (i-1)*c + y1;
qr = (i-1)*c + y2;
set(1, 1, n);
}
break;
case 3:
_sum = 0, _min = INF, _max = -INF;
for(int i = x1; i <= x2; i++) {
ql = (i-1)*c + y1;
qr = (i-1)*c + y2;
query(1, 1, n);
}
printf("%d %d %d\n", _sum, _min, _max);
break;
}
}
}
return 0;
}