题目描述
如题,已知一个数列,你需要进行下面两种操作:
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<iostream> #include<cstdio> 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||tr<l) { return 0; } if(tl<=l&&r<=tr) { return tree[i].sum; } update(l,r,i); int mid=(l+r)/2; return query(tl,tr,l,mid,i*2)+query(tl,tr,mid+1,r,i*2+1); } void add(int tl,int tr,int l,int r,int i,int val) { if(tl>r||tr<l) { return; } if(tl<=l&&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(" "); for(int i=1;i<=m;i++) { char ch; int l,r,v; scanf("%c",&ch); if(ch=='2') { scanf("%d%d ",&l,&r); ans=query(l,r,1,n,1); printf("%lld ",ans); } else { scanf("%d%d%d ",&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 ",ans); // } // } }