上帝造题的七分钟(ybtoj-树状数组)

本文详细介绍了如何利用二维差分和树状数组解决编程中的问题,探讨了空间复杂度的重要性,并提供了相关代码实现。在解决过程中,作者遇到了内存限制(MLE)的问题,强调了对空间复杂度的敏感性是提高代码质量的关键。文章通过实例展示了矩阵更新和查询的操作,以及在洛谷平台上的实践体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

在这里插入图片描述

解析

差点活活恶心死
搬砖题
(其实细节没有那么多,还是代码能力太差)

利用矩阵的二维差分
加上树状数组搞一搞
就完事了(我实在不想再写了

洛谷的双倍经验没有那么好水
MLE
这题洛谷的空间限制非常苛刻
几乎没有多余的空间

以后要增强对空间复杂度的敏感性

代码

(看我的print就能看出我调了多久)

#include<bits/stdc++.h>
using namespace std;
const int N=2050;
#define ll long long
int d[N][N];
ll id[N][N],jd[N][N],ijd[N][N];
int n,m;

void add_d(int x,int y,ll v){
//	printf("\nx=%d y=%d v=%lld\n",x,y,v);
	for(int i=x;i<=n;i+=i&-i){
		for(int j=y;j<=m;j+=j&-j){
			d[i][j]+=v;
//			printf("x=%d y=%d\n",i,j);
		}
	}
}
ll ask_d(int x,int y){
//	printf("\nask:\nx=%d y=%d\n",x,y);
	ll ans=0;
	for(int i=x;i;i-=i&-i){
		for(int j=y;j;j-=j&-j){
			ans+=d[i][j];
		} 
	}
	return ans;
}
void add_id(int x,int y,ll v){
	v*=x;
//	printf("\nx=%d y=%d v=%lld\n",x,y,v);
	for(int i=x;i<=n;i+=i&-i){
		for(int j=y;j<=m;j+=j&-j) id[i][j]+=v;//printf("x=%d y=%d\n",i,j);
	}
}
ll ask_id(int x,int y){
	ll ans=0;
//	printf("ask:x=%d y=%d\n------------\n",x,y);
	for(int i=x;i;i-=i&-i){
		for(int j=y;j;j-=j&-j){
			ans+=id[i][j];
//			printf("x=%d y=%d\n",i,j);
		} 
	}
	return ans;
}
void add_jd(int x,int y,ll v){
	v*=y;
	for(int i=x;i<=n;i+=i&-i){
		for(int j=y;j<=m;j+=j&-j) jd[i][j]+=v;
	}
}
ll ask_jd(int x,int y){
	ll ans=0;
	for(int i=x;i;i-=i&-i){
		for(int j=y;j;j-=j&-j){
			ans+=jd[i][j];
		} 
	}
	return ans;
}
void add_ijd(int x,int y,ll v){
	v*=x*y;
	for(int i=x;i<=n;i+=i&-i){
		for(int j=y;j<=m;j+=j&-j) ijd[i][j]+=v;
	}
}
ll ask_ijd(int x,int y){
	ll ans=0;
	for(int i=x;i;i-=i&-i){
		for(int j=y;j;j-=j&-j){
			ans+=ijd[i][j];
		} 
	}
	return ans;
}

void add(int x1,int y1,int x2,int y2,ll v){
	add_d(x1,y1,v);
	add_d(x2+1,y2+1,v);
	add_d(x1,y2+1,-v);
	add_d(x2+1,y1,-v);
	
	add_id(x1,y1,v);
	add_id(x2+1,y2+1,v);
	add_id(x1,y2+1,-v);
	add_id(x2+1,y1,-v);
	
	add_jd(x1,y1,v);
	add_jd(x2+1,y2+1,v);
	add_jd(x1,y2+1,-v);
	add_jd(x2+1,y1,-v);
	
	add_ijd(x1,y1,v);
	add_ijd(x2+1,y2+1,v);
	add_ijd(x1,y2+1,-v);
	add_ijd(x2+1,y1,-v);
}
ll ask(int x,int y){
//	printf("ok%lld\n",d[2][1]);
//	n--;m--;
	ll res=(x*y+x+y+1)*ask_d(x,y)+ask_ijd(x,y)-(y+1)*ask_id(x,y)-(x+1)*ask_jd(x,y);
//	printf("x=%d y=%d d=%lld id=%lld jd=%lld ijd=%lld ans=%lld\n",x,y,
//	ask_d(x,y),ask_id(x,y),ask_jd(x,y),ask_ijd(x,y),res);
//	cout<<res<<endl;
//	n++;m++;
	return res;
}
int main(){
//	printf("%d",sizeof(d)/1024/1024);
	char flag;
	scanf("%c%d%d",&flag,&n,&m);
//	add_id(1,1,2);add_id(2,2,1);
//	printf("%lld\n",ask_id(3,3));
	int a,b,c,e,w;
	while(scanf(" %c",&flag)!=EOF){
		if(flag=='L'){
			scanf("%d%d%d%d%d",&a,&b,&c,&e,&w);
			add(a,b,c,e,w);
//			printf("okk:%lld\n",ask_d(1,1));
		}
		else{
			scanf("%d%d%d%d",&a,&b,&c,&e);
//			printf("okk:%lld\n",ask_d(1,1));
			printf("%lld\n",ask(c,e)+ask(a-1,b-1)-ask(a-1,e)-ask(c,b-1));
		}
//		printf("------------opp:%lld\n",ask_id(3,3));
	}	
	return 0;
}
/*

*/

thanks for reading!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值