https://blog.csdn.net/lawrence_jang/article/details/8054173
转
树状数组模板区间更新 区间询问
14、树状数组
(1)、单点增减+区间求和
思路:C[x]表示该点的元素:sum(x)=C[1]+C[2]+……C[x]
-
int arr[MAXN];
-
inline int sum(int x){
int res=
0;
while(x)res+=arr[x],x-=lowbit(x);
return res;}
-
inline void add(int x,int n){
while(x<MAXN)arr[x]+=n,x+=lowbit(x);}
-
inline int query(int x,int y){
return sum(y)-sum(x
-1);}
(2)、区间增减+单点查询
思路:C[x]表示该点元素与左边元素的差值:num[x]=C[1]+C[2]+……C[x]
-
int arr[MAXN]
-
inline int sum(int x){
int res=
0;
while(x)res+=arr[x],x-=lowbit(x);
return res;}
-
inline void add(int x,int n){
while(x<MAXN)arr[x]+=n,x+=lowbit(x);}
-
inline int update(int x,int y,int n){add(x,n);add(y+
1,-n);}
(3)、区间增减+区间查询
思路:C1[x]表示该点元素与左边的差值,C2[x]表示的是x*C[x]
-
sum(sum(C[j],j<=i)i<=x)
-
= x*C[
1]+(x
-1)*C[
2]+……+C[x]
-
=(x+
1)*sum(C[i],i<=x)-sum(i*C[i],i<=x);
则可以想到用C1[x]维护C[x]的值,C2[x]维护x*C[X]的值
-
template <
typename X>
-
struct tree_array{
-
struct tree_array_single{
-
X arr[MAXN];
-
void add(int x,X n){
while(x<=N)arr[x]+=n,x+=lowbit(x);}
-
X sum(int x){X sum=
0;
while(x)sum+=arr[x],x-=lowbit(x);
return sum;}
-
}T1,T2;
-
void reset(){CLR(T1.arr,
0); CLR(T2.arr,
0);}
-
void add(int x,X n){T1.add(x,n);T2.add(x,x*n);}
-
void update(int L,int R,int n){add(L,n);add(R+
1,-n);}
-
X sum(int x){
return (x+
1)*T1.sum(x)-T2.sum(x);}
-
X query(int L,int R){
return sum(R)-sum(L
-1);}
-
};
15、多维树状数组
①单点增减(add) + 矩形求和(query)
②矩形增减(update) + 单点求值(sum)
-
int arr[MAXN][MAXN]
-
inline void add(int x,int y,int n) {
-
for(
int i=x;i<MAXN;i+=lowbit(i))
-
for(
int j=y;j<MAXN;j+=lowbit(j))
-
arr[i][j]+=n;
-
}
-
inline int sum(int x,int y){
-
int res=
0;
-
for(
int i=x;i;i-=lowbit(i))
-
for(
int j=y;j;j-=lowbit(j))
-
res+=arr[i][j];
-
return res;
-
}
-
inline int query(int L,int B,int R,int T) {
-
return sum(R,T)+sum(L
-1,B
-1)-sum(R,B
-1)-sum(L
-1,T);
-
}
-
inline void update(int L,int B,int R,int T,int n){
-
update(L,B,n);update(L,T+
1,n);update(R+
1,B,n);update(R+
1,T+
1,n);
-
}
③矩形增减(update)+ 矩形求和(query)
-
template<
typename X>
-
class tree_array{
-
struct tree_array_single{
-
X arr[MAXN][MAXN];
-
void add(int x,int y,X n){
-
for(
int i=x; i<MAXN; i+=lowbit(i))
-
for(
int j=y; j<MAXN; j+=lowbit(j))
-
arr[i][j]+=n;
-
}
-
X sum(int x,int y){
-
X res=
0;
-
for(
int i=x; i; i-=lowbit(i))
-
for(
int j=y; j; j-=lowbit(j))
-
res+=arr[i][j];
-
return res;
-
}
-
} T1,T2,T3,T4;
-
void add(int x,int y,int n){
-
T1.add(x,y,n);T2.add(x,y,y*n);T3.add(x,y,x*n);T4.add(x,y,x*y*n);
-
}
-
X sum(int x,int y){
-
return (x+
1)*(y+
1)*T1.sum(x,y)-(x+
1)*T2.sum(x,y)-(y+
1)*T3.sum(x,y)+T4.sum(x,y);}
-
public:
-
void init(){CLR(T1.arr,
0);CLR(T2.arr,
0);CLR(T3.arr,
0);CLR(T4.arr,
0);}
-
void update(int L,int B,int R,int T,int n){
-
add(L,B,n);add(L,T+
1,-n);add(R+
1,B,-n);add(R+
1,T+
1,n);
-
}
-
X query(int L,int B,int R,int T){
-
return sum(R,T)-sum(L
-1,T)-sum(R,B
-1)+sum(L
-1,B
-1);
-
}
-
};
④单点增减(add) + 立方体求和(query)
⑤立方体增减(update) + 单点求值(sum)
-
int arr[MAXN][MAXN][MAXN];
-
inline int sum(int x,int y,int z){
-
int res=
0;
-
for(
int i=x;i;i-=lowbit(i))
-
for(
int j=y;j;j-=lowbit(j))
-
for(
int k=z;k;k-=lowbit(k))
-
res^=arr[i][j][k];
-
return res;
-
}
-
inline void add(int x,int y,int z,int n){
-
for(
int i=x;i<MAXN;i+=lowbit(i))
-
for(
int j=y;j<MAXN;j+=lowbit(j))
-
for(
int k=z;k<MAXN;k+=lowbit(k))
-
arr[i][j][k]+=n;
-
}
-
inline void update(int x1,int y1,int z1,int x2,int y2,int z2,int n){
-
add(x1,y1,z1,n);
-
add(x2+
1,y1,z1,-n);add(x1,y2+
1,z1,-n);add(x1,y1,z2+
1,-n);
-
add(x2+
1,y2+
1,z1,n);add(x2+
1,y1,z2+
1,n);add(x1,y2+
1,z2+
1,n);
-
add(x2+
1,y2+
1,z2+
1,-n);
-
}
-
inline int query(int x1,int y1,int z1,int x2,int y2,int z2){
-
return sum(x2,y2,z2)
-
-sum(x2,y2,z1
-1)-sum(x2,y1
-1,z2)-sum(x1
-1,y2,z2)
-
+sum(x2,y1
-1,z1
-1)+sum(x1
-1,y2,z1
-1)+sum(x1
-1,y1
-1,z2)
-
-sum(x1
-1,y1
-1,z1
-1);
-
}
⑥立方体增减(update) + 立方体求和(query)///随便写写……复杂度较高
-
template<
typename X>
-
class tree_array_Cube{
-
struct tree_array_single{
-
X arr[MAXN][MAXN][MAXN];
-
X sum(int x,int y,int z){
-
X res=
0;
-
for(
int i=x;i;i-=lowbit(i))
-
for(
int j=y;j;j-=lowbit(j))
-
for(
int k=z;k;k-=lowbit(k))
-
res+=arr[i][j][k];
-
return res;
-
}
-
void add(int x,int y,int z,X n){
-
for(
int i=x;i<MAXN;i+=lowbit(i))
-
for(
int j=y;j<MAXN;j+=lowbit(j))
-
for(
int k=z;k<MAXN;k+=lowbit(k))
-
arr[i][j][k]+=n;
-
}
-
}T1,T2,T3,T4,T5,T6,T7,T8;
-
void add(int x,int y,int z,X n){
-
T1.add(x,y,z,n);
-
T2.add(x,y,z,x*n);T3.add(x,y,z,y*n);T4.add(x,y,z,z*n);
-
T5.add(x,y,z,x*y*n);T6.add(x,y,z,y*z*n);T7.add(x,y,z,x*z*n);
-
T8.add(x,y,z,x*y*z*n);
-
}
-
X sum(int x,int y,int z){
-
return (x+
1)
(y+1)(z+
1)
T1.sum(x,y,z)
-
-(y+
1)(z+
1)
T2.sum(x,y,z)-(x+1)(z+
1)
T3.sum(x,y,z)-(x+1)(y+
1)*T4.sum(x,y,z)
-
+(z+
1)*T5.sum(x,y,z)+(x+
1)*T6.sum(x,y,z)+(y+
1)*T7.sum(x,y,z)-T8.sum(x,y,z);
-
}
-
public:
-
void init(){
-
CLR(T1.arr,
0);CLR(T2.arr,
0);CLR(T3.arr,
0);CLR(T4.arr,
0);
-
CLR(T5.arr,
0);CLR(T6.arr,
0);CLR(T7.arr,
0);CLR(T8.arr,
0);
-
}
-
void update(int x1,int y1,int z1,int x2,int y2,int z2,X n){
-
add(x1,y1,z1,n);
-
add(x2+
1,y1,z1,-n);add(x1,y2+
1,z1,-n); add(x1,y1,z2+
1,-n);
-
add(x2+
1,y2+
1,z1,n);add(x2+
1,y1,z2+
1,n);add(x1,y2+
1,z2+
1,n);
-
add(x2+
1,y2+
1,z2+
1,-n);
-
}
-
X query(int x1,int y1,int z1,int x2,int y2,int z2){
-
return sum(x2,y2,z2)
-
-sum(x2,y2,z1
-1)-sum(x2,y1
-1,z2)-sum(x1
-1,y2,z2)
-
+sum(x2,y1
-1,z1
-1)+sum(x1
-1,y2,z1
-1)+sum(x1
-1,y1
-1,z2)
-
-sum(x1
-1,y1
-1,z1
-1);
-
}
-
};
16、树状数组—区间最大值
-
inline void init()
-
{
-
CLR(arr,
0);
-
for(
int i=
1;i<=N;++i)
-
for(
int j=i;j<=N&&arr[j]<num[i];j+=lowbit(j))
-
arr[j]=num[i];
-
}
-
inline int query(int L,int R)
-
{
-
int res=
0;
-
for(--L;L<R;){
-
if(R-lowbit(R)>=L){res=max(res,arr[R]);R-=lowbit(R);}
-
else{res=max(res,num[R]);--R;}
-
}
-
return res;
-
}
-
inline void update(int x,int val)
-
{
-
int ori=num[x];
-
num[x]=val;
-
if(val>=ori)
-
for(
int i=x;i<=N&&arr[i]<val;i+=lowbit(i))
-
arr[i]=val;
-
else{
-
for(
int i=x;i<=N&&arr[i]==ori;i+=lowbit(i))
-
{
-
arr[i]=val;
-
for(
int j=lowbit(i)>>
1;j;j>>=
1)
-
arr[i]=max(arr[i],arr[i-j]);
-
}
-
}
-
}