1540:打鼹鼠_二维树状数组 (数据加强版也能过)

  • 这道题我曾找过许多博客,没有能AC的,故特作此文。
  • 题干传送门
  • 先谈谈做本题的心路历程:
  • 第一眼见:哇!二维的树状数组,虽然没见过,但是貌似不难
  • 此时代码
#include<bits/stdc++.h>
using namespace std;
int n,m,dis[5001][5001],a,b,c,d,t,k;
int lowbit(int x){
	return x&(-x);
}
void add(int x,int y,int z){
	while(x<=n){
		int y1=y;
		while(y1<=m){
			dis[x][y1]+=z;
			y1+=lowbit(y1);
		}
		x+=lowbit(x);
	}
	return;
}
int sum(int x,int y){
	int ans=0;
	while(x>0){
		int y1=y;
		while(y1>0){
			ans+=dis[x][y1];
			y1-=lowbit(y1);
		}
		x-=lowbit(x);
	}
	return ans;
}
int main(){
	scanf("%d %d",&n,&m);
	while(scanf("%d",&t)!=EOF){
		if(t==1){
			scanf("%d %d %d",&a,&b,&k);
			add(a,b,k);
		}
		else if(t==2){
			scanf("%d %d %d %d",&a,&b,&c,&d);
			printf("%d\n",sum(c,d)-sum(a-1,d)-sum(c,b-1)+sum(a-1,b-1));
		}
	}
	return 0;
}
  • 然后就长这样:
  • 最后一个点WA了,一想,没错,没开long long…没事,改一下
    在这里插入图片描述
  • 数据加强后,开long long会超时,(我以前就做过int改long long会WA掉的,貌似是大量运算时long long更长更耗时)
  • 这个超时就很让人无奈,因为树状数组已经非常快,算法本身已是最优,这让人咋改?
  • 于是,上网,找大神博客,but,这道题数据加强过,so,网上的代码集体超时
  • 自己魔改了亿小下,终于AC了,(真·擦边过,999MS,还有谁!!!)在这里插入图片描述
    -代码
#include<bits/stdc++.h>
using namespace std;
int n,m;
long long dis[5001][5001];
int a,b,c,d,t,k;
char ch;
int read(){
	ch=getchar();
	int x=0;
	while(!isdigit(ch)) ch=getchar();
	while(isdigit(ch)){
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return x;
}
inline int lowbit(int x){
	return x&(-x);
}
inline void add(int x,int y,int z){
	while(x<=n){
		int y1=y;
		while(y1<=m){
			dis[x][y1]+=z;
			y1+=lowbit(y1);
		}
		x+=lowbit(x);
	}
	return;
}
inline long long sum(int x,int y){
	long long ans=0;
	while(x>0){
		int y1=y;
		while(y1>0){
			ans+=dis[x][y1];
			y1-=lowbit(y1);
		}
		x-=lowbit(x);
	}
	return ans;
}
int main(){
//	scanf("%d %d",&n,&m);
	n=read();m=read();
	while(scanf("%d",&t)!=EOF){
		if(t==1){
		//	scanf("%d %d %d",&a,&b,&k);
			a=read();b=read();//k=read();	
			scanf("%d",&k);
			add(a,b,k);
		}
		else if(t==2){
		//	scanf("%d %d %d %d",&a,&b,&c,&d);
			a=read();b=read();c=read();//d=read();
			scanf("%d",&d);
			long long ans1=0;
			int x=c,y=d;
			while(x>0){
				int y1=y;
				while(y1>0){
					ans1+=dis[x][y1];
					y1-=lowbit(y1);
				}
				x-=lowbit(x);
			}
			long long ans2=0;
			x=a-1,y=d;
			while(x>0){
				int y1=y;
				while(y1>0){
					ans2+=dis[x][y1];
					y1-=lowbit(y1);
				}
				x-=lowbit(x);
			}
			long long ans3=0;
			x=c,y=b-1;
			while(x>0){
				int y1=y;
				while(y1>0){
					ans3+=dis[x][y1];
					y1-=lowbit(y1);
				}
				x-=lowbit(x);
			}
			long long ans4=0;
			x=a-1,y=b-1;
			while(x>0){
				int y1=y;
				while(y1>0){
					ans4+=dis[x][y1];
					y1-=lowbit(y1);
				}
				x-=lowbit(x);
			}
			long long ans=ans1-ans2-ans3+ans4;
			printf("%lld\n",ans);
		}
		if(ch==EOF) break;
	}
	return 0;
}
  • 当然,这是极端情况,我用大号分是酱紫的
    在这里插入图片描述
  • 总之,这道题由于测点11数据要用long long而变得十分恶心,但魔改一下就可以过了。
  • ps.不过可以试着多交两遍
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值