被bug折磨好久,关于add操作中递归部分一个疏漏,而且测试样例比较弱也看不出来,写代码的时候脑子一定要非常清楚,避免类似低级错误。
一直纠结二位线段树的写法,结果树套树方法纠结很久着手写才发现空间复杂度是根本容不下的。
- 线段树空间一般是原数组4倍,或者比 数组大小 大的最小2的幂的两倍,这道题是需要利用后一个结论的
- 虽然这道题不能用来练手树套树,不过思路差不多,一行维护一个线段树,关于add操作是否需要考虑永久化标记,考虑到题目还有set操作,代码思路还是一致为好,对于add的维护有些类似set
#include <iostream>
#include <algorithm>
#include <queue>
#include <string>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cstdint>
#include <cassert>
#include <cmath>
#include <string>
#include <stack>
#include <map>
#include <set>
#include <deque>
#include <unordered_map>
using namespace std;
const int INF= 1<<30;
const int maxs= (1<<21)+100;
struct SegY
{
int l, r;
int mx, mn, sm;
int setv, addv;
};
struct SegX
{
SegY sty[maxs];
void build(int x, int l, int r)
{
if (l > r){
return;
}
sty[x].l= l;
sty[x].r= r;
sty[x].mx= sty[x].mn= sty[x].sm= 0;
sty[x].setv= -1;
sty[x].addv= 0;
if (l == r){
return;
}
int mid= (l+r)>>1;
build(x<<1, l, mid);
build(x<<1|1, mid+1, r);
}
int qMax(const int x, const int L, const int R)
{
if (L <= sty[x].l && R >= sty[x].r){
return sty[x].mx;
}
PushD(x);
int mid= (sty[x].l+sty[x].r)>>1;
if (R <= mid){
return qMax(x<<1, L, R);
} else if (L > mid){
return qMax(x<<1|1, L, R);
} else{
return max(qMax(x<<1, L, R), qMax(x<<1|1, L, R));
}
}
int qMin(const int x, const int L, const int R)
{
if (L <= sty[x].l && R >= sty[x].r){
return sty[x].mn;
}
PushD(x);
int mid= (sty[x].l+sty[x].r)>>1;
if (R <= mid){
return qMin(x<<1, L, R);
} else if (L > mid){
return qMin(x<<1|1, L, R);
} else{
return min(qMin(x<<1, L, R), qMin(x<<1|1, L, R));
}
}
int qSum(const int x, const int L, const int R)
{
if (L <= sty[x].l && R >= sty[x].r){
return sty[x].sm;
}
PushD(x);
int mid= (sty[x].l+sty[x].r)>>1;
if (R <= mid){
return qSum(x<<1, L, R);
} else if (L > mid){
return qSum(x<<1|1, L, R);
} else{
return qSum(x<<1, L, R)+qSum(x<<1|1, L, R);
}
}
void setNd(const int x, const int v)
{
sty[x].mx= sty[x].mn= v;
sty[x].sm= (sty[x].r-sty[x].l+1)*v;
sty[x].setv= v;
sty[x].addv= 0;
}
void addNd(const int x, const int v)
{
sty[x].mx+= v;
sty[x].mn+= v;
sty[x].sm+= (sty[x].r-sty[x].l+1)*v;
sty[x].addv+= v;
}
void PushD(int x)
{
if (sty[x].l == sty[x].r){
sty[x].setv= -1;
sty[x].addv= 0;
return;
}
int lc= x<<1, rc= x<<1|1;
int setv= sty[x].setv, addv= sty[x].addv;
if (~setv && addv){
setv+= addv;
addv= 0;
}
if (~setv){
setNd(lc, setv);
setNd(rc, setv);
} else if (addv){
addNd(lc, addv);
addNd(rc, addv);
}
sty[x].setv= -1;
sty[x].addv= 0;
}
void PushU(int x)
{
if (sty[x].l == sty[x].r){
return;
}
int lc= x<<1, rc= x<<1|1;
sty[x].mx= max(sty[lc].mx, sty[rc].mx);
sty[x].mn= min(sty[lc].mn, sty[rc].mn);
sty[x].sm= sty[lc].sm+sty[rc].sm;
}
void set(const int x, const int L, const int R, const int v)
{
if (L <= sty[x].l && R >= sty[x].r){
setNd(x, v);
return;
}
int mid= (sty[x].l+sty[x].r)>>1;
PushD(x);
if (L <= mid){
set(x<<1, L, R, v);
}
if (R > mid){
set(x<<1|1, L, R, v);
}
PushU(x);
}
void add(const int x, const int L, const int R, const int v)
{
if (L <= sty[x].l && R >= sty[x].r){
addNd(x, v);
return;
}
int mid= (sty[x].l+sty[x].r)>>1;
PushD(x);
if (L <= mid){
add(x<<1, L, R, v);
}
if (R > mid){
add(x<<1|1, L, R, v);
}
PushU(x);
}
}stx[23];
int r, c, m;
int X1, Y1, X2, Y2;
inline void Build()
{
for (int i= 1; i <= r; ++i){
stx[i].build(1, 1, c);
}
}
inline int qMax()
{
int ret= -INF;
for (int i= X1; i <= X2; ++i){
ret= max(ret, stx[i].qMax(1, Y1, Y2));
}
return ret;
}
inline int qMin()
{
int ret= INF;
for (int i= X1; i <= X2; ++i){
ret= min(ret, stx[i].qMin(1, Y1, Y2));
}
return ret;
}
inline int qSum()
{
int ret= 0;
for (int i= X1; i <= X2; ++i){
ret+= stx[i].qSum(1, Y1, Y2);
}
return ret;
}
inline void Set(int v)
{
for (int i= X1; i <= X2; ++i){
stx[i].set(1, Y1, Y2, v);
}
}
inline void Add(int v)
{
for (int i= X1; i <= X2; ++i){
stx[i].add(1, Y1, Y2, v);
}
}
int main(int argc, char const *argv[])
{
while (3 == scanf("%d%d%d", &r, &c, &m)){
Build();
int v, tp;
while (m--){
scanf("%d", &tp);
if (1 == tp){
scanf("%d%d%d%d%d", &X1, &Y1, &X2, &Y2, &v);
Add(v);
} else if (2 == tp){
scanf("%d%d%d%d%d", &X1, &Y1, &X2, &Y2, &v);
Set(v);
} else{
scanf("%d%d%d%d", &X1, &Y1, &X2, &Y2);
printf("%d %d %d\n", qSum(), qMin(), qMax());
}
}
}
return 0;
}