样例没过的线段树求调
查看原帖
样例没过的线段树求调
685429
1234567890hh楼主2023/8/24 11:01
using namespace std;
typedef long long ll;
struct node{
	int l,r,lazy=0;
	ll ans;
}tree[500001];//线段树
long dat[100000];//存放原数据
int n,m;
bool inRange(int l,int r,int L,int R);
void pushdown(int i);
void build(int l,int r,int p){
	tree[p].l=l;
	tree[p].r=r;
	if(l==r){
		tree[p].ans=dat[l];
		return;
	}
	ll mid=(l+r)>>1;//右移1位等价于除以2
	build(l,mid,(p<<1));//左移一位等价于乘以二
	build(mid+1,r,(p<<1)|1);//左移后末位必是0,与1按位或相当于加1
	tree[p].ans=tree[p<<1].ans+tree[(p<<1)|1].ans;
}
void change(int i,int l,int r,int k){
	if(tree[i].r<=r&&tree[i].l>=l){
		tree[i].ans+=k*(tree[i].r-tree[i].l+1);
		tree[i].lazy+=k;
		return;
	}else{
		if(tree[i].lazy!=0){
			pushdown(i);
		}
		if(tree[i*2].r>=l){
			change(i*2,l,r,k);
		}
		if(tree[i*2+1].l<=r){
			change(i*2+1,l,r,k);
		}
		tree[i].ans=tree[i*2].ans+tree[i*2+1].ans;
	}
}
void pushdown(int i){
	tree[i*2].lazy+=tree[i].lazy;
	tree[i*2+1].lazy+=tree[i].lazy;
	ll mid=(tree[i].r+tree[i].l)>>1;
	tree[i*2].ans+=tree[i].lazy*(mid-tree[i].l+1);
	tree[i*2+1].ans+=tree[i].lazy*(tree[i].r-mid);
	tree[i].lazy=0;
}
ll ask(int i,int l,int r){
	if(inRange(tree[i].l,tree[i].r,l,r)){
		return (tree[i].ans);
	}else{
		ll t=0;
		if(tree[i*2].r>=l){
			t+=ask(i*2,l,r);
		}
		if(tree[i*2+1].l<=r){
			t+=ask(i*2+1,l,r);
		}
		return t;
	}
}
bool inRange(int l,int r,int L,int R){
	if(L<=l&&R>=r)return true;
	else
		return false;
}
int main(){
	ios::sync_with_stdio(false);
	cin>>n>>m;
	for(int i=1;i<=n;i++)cin>>dat[i];
	build(1,n,1);//l,r,p
	int p,x,y,k;
	for(int i=1;i<=m;i++){
		cin>>p;
		if(p==1){//区间加
			cin>>x>>y>>k;
			change(1,x,y,k);//从根节点1开始搜,把区间[x,y]加上k
		}else{//区间求和
			cin>>x>>y;
			cout<<ask(1,x,y)<<endl;
		}
	}
	return 0;
}

样例输入 5 5 1 5 4 2 3 2 2 4 1 2 3 2 2 3 4 1 1 5 1 2 1 4 输出: 11 8 16 似乎是1-5区间加一的时候没加上 大佬求调

2023/8/24 11:01
加载中...