用分块写的线段树板子题结果洛谷AC,LOJ爆0了
查看原帖
用分块写的线段树板子题结果洛谷AC,LOJ爆0了
236476
Robertspot楼主2020/8/1 22:51

如题,代码在:https://www.luogu.com.cn/record/36194691

在这粘贴一份:

真的debug半天也没找到问题。。。。。。

(还有就是可能有人说是数据范围的问题,但是我在loj上提交的时候注意到了范围是1e6所以提交的时候改成了N为1000010如下代码;loj网址是https://loj.ac/submission/887397)

#include<bits/stdc++.h>
#define ll long long
#define N 1000010
using namespace std;
ll n,m,sq,num,_re; 		//每一块有sq个数字,有num个整块 
bool yes;	//所有块是否为整块,false说明有多余的数字 
ll a[N];	//原数组 
ll tag[N],sum[N];					//tag是lazy标记,sum是这一个分块的和 
ll _a,_x,_y,_k;
bool ls(ll x);
bool rs(ll x);
ll ln(ll x);
ll rn(ll x);
void update(ll x,ll y,ll z);		//x到y所有数均加上k 
ll query(ll x,ll y);				//查询x到y所有数的和 
ll belong(ll x);
int main(){
	scanf("%lld%lld",&n,&m);
	for(int i=1;i<=n;i++){
		scanf("%lld",&a[i]);
	}
	sq=sqrt(n);
	num=n/sq;
	_re=n%sq;
	if(n%sq==0){
		yes=true;		//判断是否所有块都是整块 
	}
	if(!yes){
		for(int i=1;i<=num+1;i++){
			if(i==num+1){
				for(int j=(i-1)*sq+1;j<=n;j++){
					sum[i]+=a[j];
				}
			}
			else{
				for(int j=(i-1)*sq+1;j<=i*sq;j++){
					sum[i]+=a[j];
				}
			}
		}
	}
	else{
		for(int i=1;i<=num;i++){
			for(int j=(i-1)*sq+1;j<=i*sq;j++){
				sum[i]+=a[j];
			}
		}
	}
	for(int i=1;i<=m;i++){
		scanf("%lld",&_a);
		if(_a==1){
			scanf("%lld%lld%lld",&_x,&_y,&_k);
			update(_x,_y,_k);
			continue;
		}
		if(_a==2){
			scanf("%lld%lld",&_x,&_y);
			printf("%lld\n",query(_x,_y));
		}
	}
	return 0;
}
inline bool ls(ll x){
	return (x-1)%sq==0?true:false;
}
inline bool rs(ll x){
	return x%sq==0?true:false;
}
inline ll ln(ll x){					//包含的第一个整块的下标 
	return rs(x)?((x/sq)+1):(ls(x)?((x/sq)+1):(x/sq)+2);
}
inline ll rn(ll x){					//包含的最后一个整块的下标 
	return x/sq;
}
void update(ll x,ll y,ll z){
	ll left=sq*(ln(x)-1)+1,right=sq*rn(y);
	ll be;
	if(x<left){
		be=belong(x);
		for(int i=x;i<left;i++){
			a[i]+=z;
			sum[be]+=z;
		}
	}
	if(y>right){
		be=belong(y);
		for(int i=right+1;i<=y;i++){
			a[i]+=z;
			sum[be]+=z;
		}
	}
	ll ss=z*sq;
	ll _l=ln(x),_r=rn(y);
	for(int i=ln(x);i<=rn(y);i++){
		sum[i]+=ss;
		tag[i]+=z;
	}
	return ;
}
ll query(ll x,ll y){
	ll left=sq*(ln(x)-1)+1,right=sq*rn(y);
	ll _l=ln(x),_r=rn(y);
	ll esp=0;
	if(x<left){
		for(int i=x;i<left;i++){
			esp+=a[i];
		}
		esp+=tag[belong(x)]*(left-x);
	}
	if(y>right){
		for(int i=right+1;i<=y;i++){
			esp+=a[i];
		}
		esp+=tag[belong(y)]*(y-right);
	}
	for(int i=ln(x);i<=rn(y);i++){
		esp+=sum[i];
	}
	return esp;
}
ll belong(ll x){
	if(x%sq==0){
		return x/sq;
	}
	else{
		return x/sq+1;
	}
}

如有成此业者,臣定临表涕零,不知所言orz

2020/8/1 22:51
加载中...