本题数组要开大点,而且要用long long
代码:
#include<iostream>
#include<stdio.h>
using namespace std;
typedef long long ll;
const ll maxn=100010;
ll lazy[4*maxn],tr[4*maxn],r[4*maxn];
void pushdown(ll po,ll ljs,ll rjs)//向下推lazy标记
{if(lazy[po]){//通过本区间lazy标记值改变下面区间lazy标记值lazy[2*po]+=lazy[po];lazy[2*po+1]+=lazy[po];tr[2*po]+=lazy[po]*ljs;//ljs左边数量tr[2*po+1]+=lazy[po]*rjs;//rjs右边数量lazy[po]=0;}
}
void line_change(ll a,ll b,ll c,ll le,ll ri,ll po)//区间修改
{if(a<=le&&b>=ri)//当前区间完全在要进行修改的区间内{tr[po]+=c*(ri-le+1);lazy[po]+=c;//修改本区间lazy标记值ll av=(le+ri)/2;}else//只在进行修改的区间属于当前区间时进行{ll av=(le+ri)/2;pushdown(po,av-le+1,ri-av);if(a<=av)line_change(a,b,c,le,av,2*po);if(b>av)line_change(a,b,c,av+1,ri,2*po+1);tr[po]=tr[po*2]+tr[po*2+1];//自下而上对结点更新}
}
void build(ll le,ll ri,ll po)//创建树
{if(le==ri)tr[po]=r[ri];//每个叶结点else{build(le,(le+ri)/2,2*po);//左边build((le+ri)/2+1,ri,2*po+1);//右边tr[po]=tr[po*2]+tr[po*2+1];//自下而上对结点更新}
}
ll query(ll a,ll b,ll le,ll ri,ll po)//区间查询
{if(a<=le&&b>=ri)return tr[po];ll av=(le+ri)/2;pushdown(po,av-le+1,ri-av);//下推标记,不然返回的可能是修改之前的值ll sum=0;//递归返回累计答案if(a<=av)sum+=query(a,b,le,av,po*2);if(b>av)sum+=query(a,b,av+1,ri,po*2+1);return sum;
}
int main()
{ll n,m;while(scanf("%lld%lld",&n,&m)!=EOF){for(ll i=1;i<=n;++i){scanf("%lld",&r[i]);}build(1,n,1);for(ll i=0;i<m;++i){char c[2];scanf("%s",c);if(c[0]=='Q'){ll a,b;scanf("%lld%lld",&a,&b);printf("%lld\n",query(a,b,1,n,1));}if(c[0]=='C'){ll a,b,c;scanf("%lld%lld%lld",&a,&b,&c);line_change(a,b,c,1,n,1);}}}return 0;
}