Gushing over Programming Girls|

BigSmall_En

园龄:3年2个月粉丝:3关注:5

2024-12-13 21:08阅读: 5评论: 0推荐: 0

二维树状数组小记

LG1527,发现自己竟然还不会二维树状数组,赶紧恶补一下。

下面的内容是随手写的,原理不是很难

单点改,区间查

void update(int x,int y,int v){
	for(int i=x;i<=n;i+=lowbit(i)){
		for(int j=y;j<=m;j+=lowbit(j))
			c[i][j]+=v;
	}
}
int getsum(int x,int y,int v=0){
	for(int i=x;i;i-=lowbit(i)){
		for(int j=y;j;j-=lowbit(j))
			v+=c[i][j];
	}
	return v;
}

最后答案统计

\[\sum_{i=a}^{c}\sum_{i=b}^{d}a_{i,j}=s_{c,d}-s_{c-1,d}-s_{c,d-1}+s_{c-1,d-1} \]

区间改,单点查

定义差分数组 \(d_{i,j}\),每次修改操作 \(d_{a,b}\leftarrow +v,d_{c+1,b}\leftarrow-v,d_{a,d+1}\leftarrow-v,d_{c+1,d+1}\leftarrow+v\)

\[a_{x,y}=\sum_{i=1}^{x}\sum_{j=1}^{y}d_{i,j} \]

转化为单点改,区间查

区间改,区间查询

\[\begin{align} s_{x,y}&=\sum_{i=1}^{x}\sum_{j=1}^{y}a_{i,j}\\ &=\sum_{i=1}^{x}\sum_{j=1}^{y}\sum_{k=1}^{i}\sum_{l=1}^{j}d_{k,l}\\ &=\sum_{i=1}^{x}\sum_{j=1}^{y}d_{i,j}\times(x-i+1)(y-j+1)\\ &=(x+1)(y+1)\sum_{i=1}^{x}\sum_{j=1}^y d_{i,j}-(x+1)\sum_{i=1}^{x}\sum_{j=1}^{y}d_{i,j}\times j-(y+1)\sum_{i=1}^{x}\sum_{j=1}^{y}d_{i,j}\times i+\sum_{i=1}^{x}\sum_{j=1}^{y}d_{i,j}\times ij \end{align} \]

额外维护 \(d_{i,j}\times j,d_{i,j}\times i,d_{i,j}\times ij\) 的二维前缀和即可

LG4514 上帝造题的七分钟

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef pair<int,int>ttfa;

const int N=2050;
inline int lowbit(int x){return x&-x;}

int n,m;
struct BIT_2di{
	int c[N][N];
	void update(int x,int y,int v){
		for(int i=x;i<=n;i+=lowbit(i)){
			for(int j=y;j<=m;j+=lowbit(j))
				c[i][j]+=v;
		}
	}
	int getsum(int x,int y,int v=0){
		for(int i=x;i;i-=lowbit(i)){
			for(int j=y;j;j-=lowbit(j))
				v+=c[i][j];
		}
		return v;
	}
}s,si,sj,sij;

void sij_update(int x,int y,int v){
	s.update(x,y,v);
	si.update(x,y,v*x);
	sj.update(x,y,v*y);
	sij.update(x,y,v*x*y);
}
int sij_getsum(int x,int y,int v=0){
	v+=(x+1)*(y+1)*s.getsum(x,y);
	v-=(x+1)*sj.getsum(x,y);
	v-=(y+1)*si.getsum(x,y);
	v+=sij.getsum(x,y);
	return v;
}

int main(){
	char opt[3];
	scanf("%s%d%d",opt,&n,&m);
	while(scanf("%s",opt)!=EOF){
		int a,b,c,d;scanf("%d%d%d%d",&a,&b,&c,&d);
		if(opt[0]=='L'){
			int v;scanf("%d",&v);
			sij_update(a,b,v);
			sij_update(c+1,b,-v);
			sij_update(a,d+1,-v);
			sij_update(c+1,d+1,v);
		}else{
			int v=0;
			v+=sij_getsum(c,d);
			v-=sij_getsum(a-1,d);
			v-=sij_getsum(c,b-1);
			v+=sij_getsum(a-1,b-1);
			printf("%d\n",v);
		}
	}
	return 0;
}

本文作者:BigSmall_En

本文链接:https://www.cnblogs.com/BigSmall-En/p/18605845

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   BigSmall_En  阅读(5)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起