题目链接:https://www.luogu.org/problemnew/show/U22582
链接好像失效了
我用的树套树写法。
all in one 代码:
#include <cstdio>
#include <cstring>
using namespace std;
#define MAXN 2010
#define MAXM 2010
struct LAZY {
int v, l, r;
};
#define MAX_NODE1 (MAXN << 2)
#define MAX_NODE2 (MAXM << 2)
struct SGT2 {
int s[MAX_NODE1][MAX_NODE2], n1, n2;
[MAX_NODE1];
LAZY lazy1int lazy2[MAX_NODE1][MAX_NODE2];
inline int ls(int rt) {
return rt << 1;
}
inline int rs(int rt) {
return rt << 1 | 1;
}
void Init(int _n1, int _n2) {
= _n1;
n1 = _n2;
n2 (lazy1, 0, ((n1 << 2)+1) * sizeof(int));
memsetfor (int i = 0; i <= (n1 << 2); ++i) {
(s[i], 0, (n2 << 2) * sizeof(int));
memset(lazy2[i], 0, (n2 << 2) * sizeof(int));
memset}
}
void Init(int _n1, int _n2, int a[][MAXM]) {
= _n1;
n1 = _n2;
n2 (1, 1, n1, a);
Build1}
void PushUp(int d, int rt) {
[d][rt] = s[d][ls(rt)] + s[d][rs(rt)];
s}
void Build2(int d, int rt, int l, int r, int a[MAXM]) {
if (l == r) {
[d][rt] = a[l];
s} else {
int mid = (l + r) >> 1;
(d, ls(rt), l, mid, a);
Build2(d, rs(rt), mid+1, r, a);
Build2(d, rt);
PushUp}
[d][rt] = 0;
lazy2}
void Build1(int rt, int l, int r, int a[][MAXM]) {
if (l == r) {
(rt, 1, 1, n2, a[l]);
Build2} else {
int mid = (l + r) >> 1;
(ls(rt), l, mid, a);
Build1(rs(rt), mid+1, r, a);
Build1for (int i = 1; i <= (n2 << 2); ++i)
[rt][i] = s[ls(rt)][i] + s[rs(rt)][i];
s}
[rt] = LAZY{0, 0, 0};
lazy1}
void PushDown2(int d, int rt, int l, int mid, int r) {
if (lazy2[d][rt]) {
[d][ls(rt)] += lazy2[d][rt];
lazy2[d][rs(rt)] += lazy2[d][rt];
lazy2[d][ls(rt)] += lazy2[d][rt] * (mid - l + 1);
s[d][rs(rt)] += lazy2[d][rt] * (r - mid);
s[d][rt] = 0;
lazy2}
}
void Add2(int d, int rt, int l, int r, int L, int R, int v) {
if (L <= l && r <= R) {
[d][rt] += (r - l + 1) * v;
s[d][rt] += v;
lazy2} else {
int mid = (l + r) >> 1;
(d, rt, l, mid, r);
PushDown2if (L <= mid) Add2(d, ls(rt), l, mid, L, R, v);
if (mid < R) Add2(d, rs(rt), mid+1, r, L, R, v);
(d, rt);
PushUp}
}
void PushDown1(int rt, int l, int mid, int r) {
int& v = lazy1[rt].v, L = lazy1[rt].l, R = lazy1[rt].r;
if (v) {
[ls(rt)].v += v;
lazy1[rs(rt)].v += v;
lazy1(ls(rt), 1, 1, n2, L, R, v * (mid - l + 1));
Add2(rs(rt), 1, 1, n2, L, R, v * (r - mid));
Add2= 0;
v }
}
//return the width that is modified
int Add1(int rt, int l, int r, int L1, int R1, int L2, int R2, int v) {
int cnt = 0;
if (L1 <= l && r <= R1) {
= r - l + 1;
cnt (rt, l, (l + r) >> 1, r);
PushDown1[rt] = LAZY{v, L2, R2};
lazy1} else {
int mid = (l + r) >> 1;
(rt, l, mid, r);
PushDown1if (L1 <= mid) cnt = Add1(ls(rt), l, mid, L1, R1, L2, R2, v);
if (mid < R1) cnt += Add1(rs(rt), mid+1, r, L1, R1, L2, R2, v);
}
(rt, 1, 1, n2, L2, R2, v * cnt);
Add2return cnt;
}
int Sum1(int rt, int l, int r, int L1, int R1, int L2, int R2) {
if (L1 <= l && r <= R1) {
return Sum2(rt, 1, 1, n2, L2, R2);
} else {
int ans = 0, mid = (l + r) >> 1;
(rt, l, mid, r);
PushDown1if (L1 <= mid) ans = Sum1(ls(rt), l, mid, L1, R1, L2, R2);
if (mid < R1) ans += Sum1(rs(rt), mid+1, r, L1, R1, L2, R2);
return ans;
}
}
int Sum2(int d, int rt, int l, int r, int L, int R) {
if (L <= l && r <= R) {
return s[d][rt];
} else {
int ans = 0, mid = (l + r) >> 1;
(d, rt, l, mid, r);
PushDown2if (L <= mid) ans = Sum2(d, ls(rt), l, mid, L, R);
if (mid < R) ans += Sum2(d, rs(rt), mid+1, r, L, R);
return ans;
}
}
};
int main() {
int n, m, q;
static int a[MAXN][MAXM];
static SGT2 sgt2;
("%d%d%d", &n, &m, &q);
scanffor (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
("%d", a[i] + j);
scanf}
}
.Init(n, m, a);
sgt2
while (q--) {
int p, x1, y1, x2, y2;
("%d%d%d%d%d", &p, &x1, &y1, &x2, &y2);
scanfif (1 == p) {
("%d\n", sgt2.Sum1(1, 1, n, x1, x2, y1, y2));
printf} else {
int v;
("%d", &v);
scanf.Add1(1, 1, n, x1, x2, y1, y2, v);
sgt2}
}
return 0;
}
封装型代码:
#include <cstdio>
#include <cstring>
using namespace std;
#define MAXN 2010
#define MAXM 2010
inline int ls(int rt) {
return rt << 1;
}
inline int rs(int rt) {
return rt << 1 | 1;
}
#define MAX_NODE_SEGTREE (MAXM<<2)
template<typename T>
struct SGT {
[MAX_NODE_SEGTREE], lazy[MAX_NODE_SEGTREE];
T sum
void Init(int n) {
(sum, 0, (n<<2) * sizeof(T));
memset(lazy, 0, (n<<2) * sizeof(T));
memset}
void PushUp(int rt) {
[rt] = sum[ls(rt)] + sum[rs(rt)];
sum}
void Build(int rt, int l, int r, int arr[]) {
if (l == r) {
[rt] = arr[l];
sum} else {
int mid = (l+r) >> 1;
(ls(rt), l, mid, arr);
Build(rs(rt), mid+1, r, arr);
Build(rt);
PushUp}
[rt] = 0;
lazy}
void PushDown(int rt, int l, int mid, int r) {
if (lazy[rt]) {
[ls(rt)] += lazy[rt];
lazy[rs(rt)] += lazy[rt];
lazy[ls(rt)] += lazy[rt] * (mid - l + 1);
sum[rs(rt)] += lazy[rt] * (r - mid);
sum[rt] = 0;
lazy}
}
void Add(int rt, int l, int r, int L, int R, int v) {
if (L <= l && r <= R) {
[rt] += v;
lazy[rt] += (T)(r - l + 1) * v;
sum} else {
int mid = (l + r) >> 1;
(rt, l, mid, r);
PushDownif (L <= mid)
(ls(rt), l, mid, L, R, v);
Addif (mid < R)
(rs(rt), mid+1, r, L, R, v);
Add(rt);
PushUp}
}
(int rt, int l, int r, int L, int R) {
T Sumif (L <= l && r <= R)
return sum[rt];
= 0;
T ans int mid = (l + r) >> 1;
(rt, l, mid, r);
PushDownif (L <= mid)
= Sum(ls(rt), l, mid, L, R);
ans if (mid < R)
+= Sum(rs(rt), mid+1, r, L, R);
ans return ans;
}
};
#define MAX_NODE1 (MAXN << 2)
template<typename T>
struct LAZY {
;
T vint l, r;
};
template<typename T>
struct SGT2 {
<T> s[MAX_NODE1];
SGTint n2;
<T> lazy[MAX_NODE1];
LAZY
void Init(int n1, int _n2) {
= _n2;
n2 (lazy, 0, ((n1 << 2)+1) * sizeof(int));
memsetfor (int i = 0; i <= (n1 << 2); ++i)
[i].Init(n2);
s}
void Init(int n1, int _n2, int a[][MAXM]) {
= _n2;
n2 (1, 1, n1, a);
Build}
void Build(int rt, int l, int r, int a[][MAXM]) {
if (l == r) {
[rt].Build(1, 1, n2, a[l]);
s} else {
int mid = (l + r) >> 1;
(ls(rt), l, mid, a);
Build(rs(rt), mid+1, r, a);
Buildfor (int i = 1; i <= (n2 << 2); ++i)
[rt].sum[i] = s[ls(rt)].sum[i] + s[rs(rt)].sum[i];
s}
[rt] = LAZY<T>{0, 0, 0};
lazy}
void PushDown(int rt, int l, int mid, int r) {
& v = lazy[rt].v, L = lazy[rt].l, R = lazy[rt].r;
Tif (v) {
[ls(rt)].v += v;
lazy[rs(rt)].v += v;
lazy[ls(rt)].Add(1, 1, n2, L, R, v * (mid - l + 1));
s[rs(rt)].Add(1, 1, n2, L, R, v * (r - mid));
s= 0;
v }
}
//return the width that is modified
int Add(int rt, int l, int r, int L1, int R1, int L2, int R2, int v) {
int cnt = 0;
if (L1 <= l && r <= R1) {
= r - l + 1;
cnt (rt, l, (l + r) >> 1, r);
PushDown[rt] = LAZY<T>{v, L2, R2};
lazy} else {
int mid = (l + r) >> 1;
(rt, l, mid, r);
PushDownif (L1 <= mid) cnt = Add(ls(rt), l, mid, L1, R1, L2, R2, v);
if (mid < R1) cnt += Add(rs(rt), mid+1, r, L1, R1, L2, R2, v);
}
[rt].Add(1, 1, n2, L2, R2, v * cnt);
sreturn cnt;
}
(int rt, int l, int r, int L1, int R1, int L2, int R2) {
T Sumif (L1 <= l && r <= R1) {
return s[rt].Sum(1, 1, n2, L2, R2);
} else {
= 0;
T ans int mid = (l + r) >> 1;
(rt, l, mid, r);
PushDownif (L1 <= mid) ans = Sum(ls(rt), l, mid, L1, R1, L2, R2);
if (mid < R1) ans += Sum(rs(rt), mid+1, r, L1, R1, L2, R2);
return ans;
}
}
};
int main() {
int n, m, q;
static int a[MAXN][MAXM];
static SGT2<int> sgt2;
("%d%d%d", &n, &m, &q);
scanffor (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
("%d", a[i] + j);
scanf}
}
.Init(n, m, a);
sgt2
while (q--) {
int p, x1, y1, x2, y2;
("%d%d%d%d%d", &p, &x1, &y1, &x2, &y2);
scanfif (1 == p) {
("%d\n", sgt2.Sum(1, 1, n, x1, x2, y1, y2));
printf} else {
int v;
("%d", &v);
scanf.Add(1, 1, n, x1, x2, y1, y2, v);
sgt2}
}
return 0;
}