BIT 进阶

二维 BIT

简介

实际上是树状数组套树状数组,用二维数组维护。支持区间操作。

算法流程

模板题: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

posted @ 2024-12-11 20:20  ldh081122  阅读(199)  评论(0)    收藏  举报