题目描述
如题,已知一个数列,你需要进行下面两种操作:
1.将某区间每一个数加上x
2.求出某区间每一个数的和
输入输出格式
输入格式:
第一行包含两个整数N、M,分别表示该数列数字的个数和操作的总个数。
第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。
接下来M行每行包含3或4个整数,表示一个操作,具体如下:
操作1: 格式:1 x y k 含义:将区间[x,y]内每个数加上k
操作2: 格式:2 x y 含义:输出区间[x,y]内每个数的和
输出格式:
输出包含若干行整数,即为所有操作2的结果。
#include
#include
using namespace std;
struct node{
long long mark,sum;
}tree[400010];
int x[100010];
int n,m,a,b,c;
int as;
int sx,st,sk;
long long ans;
char pd;
void update(int l,int r,int i)
{
if(!tree[i].mark)
{
return;
}
int mid=(l+r)/2;
tree[i*2].sum+=tree[i].mark*(long long)(mid-l+1);
tree[i*2+1].sum+=tree[i].mark*(long long)(r-mid);
tree[i*2].mark+=tree[i].mark;
tree[i*2+1].mark+=tree[i].mark;
tree[i].mark=0;
}
long long query(int tl,int tr,int l,int r,int i)
{
if(tl>r||trr||tr=r)
{
tree[i].sum+=val*(long long)(r-l+1);
tree[i].mark+=val;
return;
}
update(l,r,i);
int mid=(l+r)/2;
add(tl,tr,l,mid,i*2,val);
add(tl,tr,mid+1,r,i*2+1,val);
tree[i].sum=tree[i*2].sum+tree[i*2+1].sum;
}
void build(int l,int r,int i)
{
if(l==r)
{
tree[i].sum=x[l];
return;
}
int mid=(l+r)/2;
build(l,mid,i*2);
build(mid+1,r,i*2+1);
tree[i].sum=tree[i*2].sum+tree[i*2+1].sum;
}
void solve()
{
build(1,n,1);
scanf("\n");
for(int i=1;i<=m;i++)
{
char ch;
int l,r,v;
scanf("%c",&ch);
if(ch=='2')
{
scanf("%d%d\n",&l,&r);
ans=query(l,r,1,n,1);
printf("%lld\n",ans);
}
else
{
scanf("%d%d%d\n",&l,&r,&v);
add(l,r,1,n,1,v);
}
}
}
int main()
{
cin>>n>>m;
for(a=1;a<=n;a++)
{
cin>>x[a];
}
solve();
// build(1,n,1);
// for(a=1;a<=m;a++)
// {
// cin>>pd;
// if(pd=='1')
// {
// scanf("%d%d%d",&sx,&st,&sk);
// add(sx,st,1,n,1,sk);
// }
// else
// {
// scanf("%d%d%d",&sx,&st);
// ans=query(sx,st,1,n,1);
// printf("%ld\n",ans);
// }
// }
}