「学习笔记」二维树状数组
本文算是水文......
二维树状数组解释起来太麻烦了,但写法和一维几乎差不多,就是加了一层循环,So,这篇文章解释会很少几乎没有
update 2022.11.4 我又回来补充点东西
单点修改,区间查询:
这个和一维的相差不大,真的只是多了层循环
#include<bits/stdc++.h>
#define ll long long
#define rll register long long
using namespace std;
ll n,m,p,x,y,z,w;
ll s[4500][4500];
void add(ll,ll,ll);
ll sum(ll,ll);
int main()
{
scanf("%lld%lld",&n,&m);
while((scanf("%lld",&p))!=EOF)
{
if(p==1)
{
scanf("%lld%lld%lld",&x,&y,&z);
add(x,y,z);
}
else
{
scanf("%lld%lld%lld%lld",&w,&x,&y,&z);
printf("%lld\n",sum(y,z)-sum(w-1,z)-sum(y,x-1)+sum(w-1,x-1));
}
}
return 0;
}
void add(ll a,ll b,ll c)
{
for(rll i=a;i<=n;i+=(i&(-i)))
{
for(rll j=b;j<=m;j+=(j&(-j)))
{
s[i][j]+=c;
}
}
}
ll sum(ll a,ll b)
{
ll ans=0;
for(rll i=a;i;i-=(i&(-i)))
{
for(rll j=b;j;j-=(j&(-j)))
{
ans+=s[i][j];
}
}
return ans;
}
区间修改,单点查询:
区间修改还是差分的思想,只不过这个差分是二维的
设差分数组为 ,原数组为 ,差分数组的前缀和为
根据差分与前缀和的关系,我们可以知道
再推下去
又因为
所以
按照二维差分的修改:让 的区域都 ,只需要在 位置和 ,在 和 即可,单点查询的做法等同于上面的区间查询
代码:
#include <bits/stdc++.h>
#define ll long long
#define rll register long long
using namespace std;
ll n, m, a, b, c, d, k, x, y, p;
ll s[4500][4500];
void add(ll, ll, ll);
ll sum(ll, ll);
int main() {
scanf("%lld%lld", &n, &m);
while ((scanf("%lld", &p)) != EOF) {
if (p == 1) {
scanf("%lld%lld%lld%lld%lld", &a, &b, &c, &d, &k);
add(a, b, k);
add(a, d + 1, -k);
add(c + 1, b, -k);
add(c + 1, d + 1, k);
}
if (p == 2) {
scanf("%lld%lld", &x, &y);
printf("%lld\n", sum(x, y));
}
}
return 0;
}
void add(ll xx, ll yy, ll zz) {
for (rll i = xx; i <= n; i += (i & (-i))) {
for (rll j = yy; j <= m; j += (j & (-j))) {
s[i][j] += zz;
}
}
}
ll sum(ll xx, ll yy) {
ll ans = 0;
for (rll i = xx; i; i -= (i & (-i))) {
for (rll j = yy; j; j -= (j & (-j))) {
ans += s[i][j];
}
}
return ans;
}
区间修改,区间查询:
跟一维的公式解释差不多,区间查询,实际就是求
继续往下推
因此,我们只要维护 即可
代码:
#include<bits/stdc++.h>
#define ll long long
#define rll register long long
using namespace std;
ll n,m;
ll s1[2400][2400],s2[2400][2400],s3[2400][2400],s4[2400][2400];
void add(ll,ll,ll);
ll sum(ll,ll);
int main()
{
ll p,a,b,c,d,x;
scanf("%lld%lld",&n,&m);
while((scanf("%lld",&p))!=EOF)
{
if(p==1)
{
scanf("%lld%lld%lld%lld%lld",&a,&b,&c,&d,&x);
add(a,b,x);
add(a,d+1,-x);
add(c+1,b,-x);
add(c+1,d+1,x);
}
else
{
scanf("%lld%lld%lld%lld",&a,&b,&c,&d);
printf("%lld\n",sum(c,d)-sum(c,b-1)-sum(a-1,d)+sum(a-1,b-1));
}
}
return 0;
}
void add(ll x,ll y,ll z)
{
for(rll i=x;i<=n;i+=(i&(-i)))
{
for(rll j=y;j<=m;j+=(j&(-j)))
{
s1[i][j]+=z;
s2[i][j]+=z*x;
s3[i][j]+=z*y;
s4[i][j]+=z*x*y;
}
}
}
ll sum(ll x,ll y)
{
ll ans=0;
for(rll i=x;i;i-=(i&(-i)))
{
for(rll j=y;j;j-=(j&(-j)))
{
ans+=((x+1)*(y+1)*s1[i][j])-((y+1)*s2[i][j])-((x+1)*s3[i][j])+s4[i][j];
}
}
return ans;
}
作者:yifan0305
出处:https://www.cnblogs.com/yifan0305/p/16426324.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
转载时还请标明出处哟!
朝气蓬勃 后生可畏
分类:
基础数据结构知识
Buy me a cup of coffee ☕.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】