简介
实际上是树状数组套树状数组,用二维数组维护。支持区间操作。
算法流程
模板题:P4514 上帝造题的七分钟
考虑对二维差分数组作二阶二维前缀和。考虑对 \((i,j)\) 加 \(d\) 对查询以 \((x,y)\) 为矩形右下角的贡献。此时对于所有的 \(a_{i\sim x,j \sim y}\) 都有 \(d\) 的贡献,那么对于 \((x,y)\) 则有 \((x-i+1)\times (y-j+1) \times d\) 的贡献。拆开可得 \((x+1)(y+1)d-(y+1)id-(x+1)jd+ijd\),分别维护 \(d,\ id,\ jd,\ ijd\) 的一阶二维前缀和即可。
复杂度 \(O(q \log n \log m)\).
struct interval_BIT {
int tr[5][N][M];
int lowbit(int x) {
return x&(-x);
}
void modify(int x,int y,ll c) {
for(int i=x;i<=n;i+=lowbit(i)) {
for(int j=y;j<=m;j+=lowbit(j)) {
tr[1][i][j]+=c;
tr[2][i][j]+=c*x;
tr[3][i][j]+=c*y;
tr[4][i][j]+=c*x*y;
}
}
}
void interval_modify(int x1,int y1,int x2,int y2,ll c) {
modify(x1,y1,c);modify(x2+1,y2+1,c);
modify(x1,y2+1,-c);modify(x2+1,y1,-c);
}
int query(int x,int y) {
int res=0;
for(int i=x;i;i-=lowbit(i)) {
for(int j=y;j;j-=lowbit(j)) {
res+=1ll*(x+1)*(y+1)*tr[1][i][j]-1ll*(y+1)*tr[2][i][j]-1ll*(x+1)*tr[3][i][j]+tr[4][i][j];
}
}
return res;
}
int interval_query(int x1,int y1,int x2,int y2) {
return query(x2,y2)-query(x1-1,y2)-query(x2,y1-1)+query(x1-1,y1-1);
}
}t;
结语
其实不是什么特别新鲜的做法吧,就是二维差分二维前缀和套个树状数组支持区间加操作。
不过代码还是不好记的,每次打都要现推。
参考文章
[1] 树状数组进阶 https://www.cnblogs.com/alex-wei/p/BIT_advanced.html
标签:前缀,树状,int,二维,数组,BIT From: https://www.cnblogs.com/ldh081122/p/18600652