70分求助
查看原帖
70分求助
681351
Tobiichi_Origami楼主2022/10/4 11:06
#include<bits/stdc++.h>
#define long long int
using namespace std;
struct tree{
	int l,r,sum=0;
	int add=0;
    //l为左端点,r为右端点,sum表示区间和,add表示对于区间中的每个点要进行操作的值
}t[1000001];
int a[1000001];
int n,m;
void pushup(int u)//由两个子节点的值更新父节点
{
	int tmp=t[u<<1].sum+t[u<<1|1].sum;
	t[u].sum=tmp;//更新
}
void pushdown(int u)//将值传给自己的子节点
{
	if(t[u].add)//如果进行操作的值不为0,就把这个值传给自己的儿子,因为为0则没有意义
	{
		t[u<<1].add+=t[u].add;//将值传给左儿子
		t[u<<1].sum+=(t[u<<1].r-t[u<<1].l+1)*t[u].add;//将儿子节点的区间和加上新的要加上的值
		t[u<<1|1].add+=t[u].add;//同理
		t[u<<1|1].sum+=(t[u<<1|1].r-t[u<<1|1].l+1)*t[u].add;
		t[u].add=0;//将这个值标记为0
	}
}
void build(int u,int l,int r)
{
	t[u].l=l;t[u].r=r;
	if(l==r) t[u].sum=a[l];//如果到了叶子结点则将区间和变为初始值
	else
	{
		int mid=(l+r)>>1;
		build(u<<1,l,mid);//左孩子
		build(u<<1|1,mid+1,r);//右孩子
		pushup(u);//因为孩子节点的区间和更新过了,所以父亲节点也要更新
	}
}
void modify(int u,int l,int r,int x)
{
	if(t[u].l>=l&&t[u].r<=r)//如果已经包含这个点,则不用分裂
	{
		t[u].sum+=(t[u].r-t[u].l+1)*x;//更新区间和
		t[u].add+=x;//将值变为要加上的值
		return;
	}
	else
	{
		pushdown(u);//传给儿子
		int mid=(t[u].l+t[u].r)>>1;
		if(l<=mid) modify(u<<1,l,r,x);//左儿子
		if(r>mid) modify(u<<1|1,l,r,x);//右儿子
		pushup(u);//更新父区间
	}
}
int query(int u,int l,int r)
{
	if(t[u].l>=l&&t[u].r<=r)//如果已经包含了这个区间,则可以直接返回区间和
		return t[u].sum;
	pushdown(u);//传给儿子
	int mid=(t[u].l+t[u].r)>>1,res=0;
	if(l<=mid) res+=query(u<<1,l,r);//左儿子的区间和
	if(r>mid) res+=query(u<<1|1,l,r);//右儿子的区间和
	return res;//返回区间和
}
signed main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>a[i];
    build(1,1,n);//建树
	while(m--)
	{
		char op;
		cin>>op;
		if(op=='C')
		{
			int x,y,z;
			cin>>x>>y>>z;
			modify(1,x,y,z);//区间修改
		}
		else
		{
			int x,y;
			cin>>x>>y;
			cout<<query(1,x,y)<<endl;//区间查询
		}
	}
	return 0;
} 
2022/10/4 11:06
加载中...