线段树模板代码求调
查看原帖
线段树模板代码求调
1068165
InfiniteRobin楼主2024/6/29 20:57

样例能过,但测试数据全WA。

#include<bits/stdc++.h>
#define lson k<<1
#define rson k<<1|1
using namespace std;
typedef long long ll; 
const int N=1e5+5;
ll n,m;
ll num[4*N];

struct node{
	ll l,r,add;
	ll num;
}a[4*N]; //线段树 4倍空间 

//下沉 
void push_down(ll k){ //a[k].l ~ a[k].r 每个数加上 a[k].add 
	
	
	ll mid=(a[k].l+a[k].r)/2;
	//左节点加上 
	a[lson].add+=a[k].add;
	//左节点下边所有节点都要加,因此该节点的值就要加上 结点个数 X add 
	a[lson].num+=(mid-a[k].l+1)*a[k].add;
	//右节点同理 
	a[rson].add+=a[k].add;
	a[rson].num+=(a[k].r-mid)*a[k].add;
	//取消该层懒标记 
	a[k].add=0;
}

void buildTree(ll k,ll x,ll y){ //k节点编号 x左范围  y右范围 
	a[k].l=x;
	a[k].r=y;
	if(x==y){ //叶子节点 直接赋值 
		a[k].num=num[x];
		return;
	}
	buildTree(lson,x,(x+y)/2); //建立左子树 
	buildTree(rson,(x+y)/2+1,y); //建立右子树 
	a[k].num=a[lson].num+a[rson].num; //求该节点的值 
}

ll sum(ll k,ll x,ll y){
	//如果 x<=l<r<=y 那么这一段全部取走 
	if(x<=a[k].l&&a[k].r<=y){
		return a[k].num;
	}
	push_down(k);
	ll ans=0,mid=(a[k].l+a[k].r)/2;
	//如果 x<=mid 说明有交叉 那么继续递归查找 
	if(x<=mid){
		ans+=sum(lson,x,y); //查找范围不能变 
	}
	if(y>=mid+1){
		ans+=sum(rson,x,y);
	}
	return ans;
}  


//区间修改 lazy-tag
void update(ll k,ll x,ll y,ll z){ //当前下标为 k 范围是 x~y 的值加上 z 
	if(x<=a[k].l&&a[k].l<=y){
		a[k].add+=z;
		//每个节点都要加 因此要加 结点个数 * z 
		a[k].num+=(a[k].r-a[k].l+1)*z; 
		return; 
	}
	//下沉,把 a[k].add 分配给它的两条线段 
	push_down(k); 
	ll ans=0,mid=(a[k].l+a[k].r)/2;
	//如果 x<=mid 说明有交叉 那么继续递归修改 
	if(x<=mid){
		update(lson,x,y,z); //范围不能变 
	}
	if(y>=mid+1){
		update(rson,x,y,z);
	}
	a[k].num=a[lson].num+a[rson].num;
} 


int main() {
	cin>>n>>m;
	
	for(ll i=1;i<=n;i++){
		cin>>num[i];
	} 
	
	buildTree(1,1,n);
	ll x,y,z;
    ll opt;
	while(m--){
		cin>>opt>>x>>y;
		if(opt==1){
			cin>>z;
			update(1,x,y,z);
		}
		else{
			cout<<sum(1,x,y)<<endl;
		}
	}
	
	return 0;
}
2024/6/29 20:57
加载中...