单点修改区间查询
题目
n
,
m
<
=
2
12
n,m<=2^{12}
n,m<=212,询问次数
<
=
3
∗
1
0
5
<=3*10^5
<=3∗105
解析
显然是一个二维树状数组,直接类似树状数组定义,然后跑一遍板子即可
注意查询时的答案要用容斥推出是
a
s
k
c
,
d
−
a
s
k
a
−
1
,
d
−
a
s
k
c
,
b
−
1
+
a
s
k
a
−
1
,
b
−
1
ask_{c,d}-ask_{a-1,d}-ask_{c,b-1}+ask_{a-1,b-1}
askc,d−aska−1,d−askc,b−1+aska−1,b−1
我居然把n,m的数据范围看成了
1
0
12
10^{12}
1012,原地放弃
code:
#include<cstdio>
#include<algorithm>
#define int long long
using namespace std;
inline bool idigit(char x){return (x<'0'|x>'9')?0:1;}
inline int read()
{
int num=0,f=1;
char c=0;
while(!idigit(c=getchar())){if(c=='-')f=-1;}
while(idigit(c))num=(num<<1)+(num<<3)+(c&15),c=getchar();
return num*f;
}
inline void write(int x)
{
int F[20];
int tmp=x>0?x:-x;
if(x<0)putchar('-');
int cnt=0;
while(tmp>0){F[cnt++]=tmp%10+'0';tmp/=10;}
while(cnt>0)putchar(F[--cnt]);
if(x==0)putchar('0');
putchar('\n');
}
inline int lowbit(int x){return x&-x;}
int tree[4100][4100],x,y,xx,yy,n,m,op,tot=0;
inline void add(int x,int y,int k){for(;x<=n;x+=lowbit(x))for(int i=y;i<=m;i+=lowbit(i))tree[x][i]+=k;}
inline int sum(int x,int y){int ans=0;while(x){for(int i=y;i;i^=lowbit(i))ans+=tree[x][i];x^=lowbit(x);}return ans;}
signed main()
{
n=read(),m=read();
while(~scanf("%lld",&op))
{
if(op==1)x=read(),y=read(),xx=read(),add(x,y,xx);
else x=read()-1,y=read()-1,xx=read(),yy=read(),write(sum(xx,yy)-sum(x,yy)-sum(xx,y)+sum(x,y));
}
return 0;
}