二维树状数组 :单点修改,区间查询(模板)
程序员文章站
2024-03-03 17:53:28
...
题目传送门
给你一个n*m的邻接矩阵,完成以下两个操作。
"1 x y k":表示元素 Ax,y 自增 k;
"2 a b c d":表示询问左上角为 (a,b),右下角为 (c,d) 的子矩阵内所有数的和。
input
输入的第一行有两个正整数 n,m;
接下来若干行,每行一个操作,直到文件结束。
output
对于每个 "2" 操作,输出一个整数,表示对于这个操作的回答。
example
Input
2 2
1 1 1 3
1 2 2 4
2 1 1 2 2
Output
7
note
1≤n,m≤2^12,1≤x,a,c≤n,1≤y,b,d≤m,|k|≤105,保证操作数目不超过 3×10^5,且询问的子矩阵存在。
基本操作和一维树状数组差不多,求和的时候注意下二维前缀和的求法就可以。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e3+5;
const int mod=1e9+7;
const int INF=0x7fffffff;
const ll LLINF=0x7fffffffffffffff;
const double EPS=1e-10;
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define pb push_back
#define pii pair<int,int>
#define pll pair<ll,ll>
#define debug cout<<"debug"<<endl;
#define ls p<<1
#define rs p<<1|1
#define int long long
int c[N][N];
int lowbit(int x)
{
return x&-x;
}
int n,m;
void add(int x,int y,int k)
{
for(int i=x;i<=n;i+=lowbit(i))
{
for(int j=y;j<=m;j+=lowbit(j))
{
c[i][j]+=k;
}
}
}
int sum(int x,int y)
{
int s=0;
for(int i=x;i;i-=lowbit(i))
{
for(int j=y;j;j-=lowbit(j))
{
s+=c[i][j];
}
}
return s;
}
signed main()
{
IOS;
//freopen("","r",stdin);
//freopen("","w",stdout);
scanf("%lld%lld",&n,&m);
int oo,x,y,z,w;
while(scanf("%lld",&oo)!=EOF)
{
if(oo==1)
{
scanf("%lld%lld%lld",&x,&y,&z);
add(x,y,z);
}
else
{
scanf("%lld%lld%lld%lld",&x,&y,&z,&w);
printf("%lld\n",sum(z,w)-sum(x-1,w)-sum(z,y-1)+sum(x-1,y-1));
}
}
}
上一篇: [模板题]归并排序