luogu P4514ybtoj树状数组课堂过关差分 例题6区间修改区间查询 & 上帝造题的七分钟
Posted SSL_ZZL
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu P4514ybtoj树状数组课堂过关差分 例题6区间修改区间查询 & 上帝造题的七分钟相关的知识,希望对你有一定的参考价值。
Link
luogu P4514 上帝造题的七分钟
ybtoj 【树状数组课堂过关】 【例题6】区间修改区间查询
题面//因为不知道侵不侵权所以就是题面是私密的,有账号的直接看转送门就可了
题目大意
给一个矩阵A,有两个操作
- 1 a, b, c, d, s=》 A ( a 到 c ) , ( b 到 d ) A_{(a到c),(b到d)} A(a到c),(b到d)+s
- 2 a, b, c, d =》求 A ( a 到 c ) , ( b 到 d ) A_{(a到c),(b到d)} A(a到c),(b到d)的和
解题思路
对,捡了道紫题的便宜
很明显,这种矩阵(区间)加值要用差分
【例题4】区间修改区间查询 这是道一维的差分题,但是这题是二维的
设a[][]是实际数组,s[][]是差分数组
a
[
i
]
[
j
]
=
∑
k
=
1
i
∑
l
=
1
j
s
[
k
]
[
l
]
a[i][j]=∑_{k=1}^{i}∑_{l=1}^{j}s[k][l]
a[i][j]=k=1∑il=1∑js[k][l]
差分时记得要容斥
add(a, b, s);
add(a, d + 1, -s);
add(c + 1, b, -s);
add(c + 1, d + 1, s);
设f[i][j]是矩阵
A
(
1
到
i
)
,
(
1
到
j
)
A_{(1到i),(1到j)}
A(1到i),(1到j)的和,那么
f
[
i
]
[
j
]
=
∑
i
a
=
1
n
∑
j
a
=
1
m
a
[
i
a
]
[
j
a
]
=
∑
i
s
=
1
n
∑
j
s
=
1
m
∑
k
=
1
i
a
∑
l
=
1
j
a
s
[
k
]
[
l
]
f[i][j]=∑_{ia=1}^n∑_{ja=1}^ma[ia][ja]=∑_{is=1}^{n}∑_{js=1}^m∑_{k=1}^{ia}∑_{l=1}^{ja}s[k][l]
f[i][j]=ia=1∑nja=1∑ma[ia][ja]=is=1∑njs=1∑mk=1∑ial=1∑jas[k][l]
和一维一样,考虑每个s[][]的出现次数
有点复杂,是不会讲的,所以。。。推篇博客?
ybtoj和luogu的输入不太一样
Code
ybtoj版
#include <iostream>
#include <cstdio>
#define ll long long
using namespace std;
int n, m, a, b, c, d, now;
ll s, tree_s[3000][3000], tree_i[3000][3000], tree_j[3000][3000], tree_ij[3000][3000];
int lowbit(int x) {return (x & -x);}
void add(int x, int y, ll s) {
for(int i = x; i <= n; i += lowbit(i))
for(int j = y; j <= m; j += lowbit(j)) {
tree_s[i][j] += s;
tree_i[i][j] += s * x;
tree_j[i][j] += s * y;
tree_ij[i][j] += s * x * y;
}
}
ll sum(int x, int y) {
ll ans = 0;
for(int i = x; i; i -= lowbit(i))
for(int j = y; j; j -= lowbit(j))
ans += tree_s[i][j] * (x + 1) * (y + 1) - tree_i[i][j] * (y + 1) - tree_j[i][j] * (x + 1) + tree_ij[i][j];
return ans;
}
int main() {
scanf("%d %d", &n, &m);
while(scanf("%d", &now) != EOF) {
scanf("%d %d %d %d", &a, &b, &c, &d);
if (now == 1) {
scanf("%lld", &s);
add(a, b, s);
add(a, d + 1, -s);
add(c + 1, b, -s);
add(c + 1, d + 1, s);
} else {
printf("%lld\\n", sum(c, d) - sum(a - 1, d) - sum(c, b - 1) + sum(a - 1, b - 1));
}
}
}
luogu版
#include <iostream>
#include <cstdio>
using namespace std;
char now;
int n, m, a, b, c, d;
int s, tree_s[3000][3000], tree_i[3000][3000], tree_j[3000][3000], tree_ij[3000][3000];
int lowbit(int x) {return (x & -x);}
void add(int x, int y, int s) {
for(int i = x; i <= n; i += lowbit(i))
for(int j = y; j <= m; j += lowbit(j)) {
tree_s[i][j] += s;
tree_i[i][j] += s * x;
tree_j[i][j] += s * y;
tree_ij[i][j] += s * x * y;
}
}
int sum(int x, int y) {
int ans = 0;
for(int i = x; i; i -= lowbit(i))
for(int j = y; j; j -= lowbit(j))
ans += tree_s[i][j] * (x + 1) * (y + 1) - tree_i[i][j] * (y + 1) - tree_j[i][j] * (x + 1) + tree_ij[i][j];
return ans;
}
int main() {
scanf("X %d %d", &n, &m);
while(~scanf("%s", &now)) {
scanf("%d %d %d %d", &a, &b, &c, &d);
if (now == 'L') {
scanf("%d", &s);
add(a, b, s);
add(a, d + 1, -s);
add(c + 1, b, -s);
add(c + 1, d + 1, s);
} else {
printf("%d\\n", sum(c, d) - sum(a - 1, d) - sum(c, b - 1) + sum(a - 1, b - 1));
}
}
}
以上是关于luogu P4514ybtoj树状数组课堂过关差分 例题6区间修改区间查询 & 上帝造题的七分钟的主要内容,如果未能解决你的问题,请参考以下文章
luogu UVA12983ybtoj例题3树状数组严格上升子序列数&The Battle of Chibi
luogu P4513ybtoj线段树课堂过关例题3小白逛公园
ybtoj 单调队列课堂过关luogu P1886例题1滑动窗口
luogu UVA10559 ybtoj 区间DP课堂过关 例题3消除木块 & 方块消除 Blocks