poj3468A Simple Problem with Integers

线段树区间更新,这题略坑,当然,自己坑自己的成分还是占大多数。。。

还是代码能力的问题,对long long和int之间的差异不敏感,导致错误,奇怪的是用int64就不会出错。。。

还有数组必须开到140000才能ac,但有人开100010照样ac,估计是我的写法有问题,尤其是pushdown那个地方

反正线段树区间更新我还很不熟练,代码需要优化

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define MAX 140000
#define lson root<<1,l,mid
#define rson root<<1|1,mid+1,r
using namespace std;

long long n,q,sum[MAX<<2],add[MAX<<2];

void pushdown(int root){
	//cout<<"c";
	if(root*2>=MAX*4-10)
		return ;
	add[root<<1]+=add[root];
	add[root<<1|1]+=add[root];
//	cout<<"down"<<root<<add[root<<1]<<add[root<<1|1]<<endl;
	add[root]=0;
}

void pushup(int root,int all){
	//	cout<<"up"<<root<<" "<<add[root<<1]<<" "<<add[root<<1|1]<<endl;
	if(add[root<<1]){
		//cout<<"b";
		sum[root<<1]+=add[root<<1]*(all-all/2);
		pushdown(root<<1);
	}
	if(add[root<<1|1]){
		//cout<<"bb";
		sum[root<<1|1]+=add[root<<1|1]*(all/2);
		pushdown(root<<1|1);
	}
	sum[root]=sum[root<<1]+sum[root<<1|1];
	return ;
}

void build(int root,int l,int r){
	add[root]=0;
	if(l==r){
		scanf("%lld",&sum[root]);
		return;
	}
	int mid=(l+r)>>1;
	build(lson);
	build(rson);
	pushup(root,r-l+1);
}

long long query(int root,int l,int r,int left,int right){
	if(l>right||r<left)
		return 0;
	//cout<<root<<endl;
	if(l>=left&&r<=right){
		//	cout<<root<<"add"<<add[root]<<endl;
			if(add[root]){
			sum[root]+=add[root]*(r-l+1);
			pushdown(root);
		}
		return sum[root];
	}
	if(add[root]){
		//	cout<<"add"<<root<<" "<<add[root]<<endl;
			pushdown(root);
	}
	int mid=(l+r)>>1;
	long long ret=query(lson,left,right);
	ret+=query(rson,left,right);
	pushup(root,r-l+1);//这步很重要,保证pushdown正确发挥作用
//	cout<<root<<"ret"<<ret<<endl;
	return ret;	
}

void update(int root,int l,int r,int left,int right,int c){
	if(l>right||r<left)
		return;
	//cout<<root<<endl;
	if(l>=left&&r<=right){
		add[root]+=c;
		sum[root]+=add[root]*(r-l+1);
		pushdown(root);
		return;
	}
	if(add[root])
		pushdown(root);
	int mid=(l+r)>>1;
	update(lson,left,right,c);
	update(rson,left,right,c);
	pushup(root,r-l+1);
}

void debug(int root,int l,int r){
//	cout<<root<<" "<<l<<" "<<r<<" "<<sum[root]<<endl;
		if(l==r){
		
		return ;
	}
	int mid=(l+r)>>1;
	debug(lson);
	debug(rson);
}

int main(){
	char com[30];
	int a,b,c;
	while(scanf("%d %d",&n,&q)!=EOF){
		build(1,1,n);
		getchar();
		for(int i=0;i<q;i++){
			gets(com);
			if(com[0]=='Q'){
				//	puts(com);
					sscanf(&com[2],"%d %d",&a,&b);
					//cout<<a<<b<<c;
				printf("%lld\n",query(1,1,n,a,b));
			}
			else{
				sscanf(&com[2],"%d %d %d",&a,&b,&c);
			//cout<<a<<b<<c;
				update(1,1,n,a,b,c);
			}
			//debug(1,1,n);
		}
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值