1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
| using namespace std; typedef long long ll; const int MAXN=100005; int a[MAXN]; int n,m; struct Node{ int l,r,tag;//l,r表示该节点表示的若干元素的区间,tag用来记录修改的值 ll sum,mx;//sum为子孙的和,mx为区间的最大值。 }tree[MAXN<<2];//线段树大小开到数组的四倍 inline int tl(int p){return p<<1;}//左孩子
inline int tr(int p){return p<<1|1;}//右孩子
inline void push_up(int p){//将p底下的子孙的值总和起来 tree[p].sum=tree[tl(p)].sum+tree[tr(p)].sum; } inline void push_down(int p){//将p的tag修改值传递下去,同时子孙的数据也要改变 if(tree[p].tag){//如果p更新过数据 int tag=tree[p].tag; tree[p].tag=0; tree[tl(p)].tag+=tag; tree[tr(p)].tag+=tag; tree[tl(p)].mx+=tag; tree[tr(p)].mx+=tag; tree[tl(p)].sum+=(tree[tl(p)].r-tree[tl(p)].l+1)*tag; tree[tr(p)].sum+=(tree[tr(p)].r-tree[tr(p)].l+1)*tag; } } void build(int p,int l,int r){//建立线段树 tree[p].l=l,tree[p].r=r; if(l==r){ tree[p].sum=a[l]; tree[p].mx=a[l]; return; } int mid=(l+r)>>1; build(tl(p),l,mid);//建立左树 build(tr(p),mid+1,r);//建立右树 push_up(p); } void modify(int p,int l,int r,int val){ if(l<=tree[p].l&&r>=tree[p].r){//如果有一段区间被包含在要修改的区间,直接进行修改,不需要从子树的左右子树找 tree[p].tag+=val; tree[p].sum+=(tree[p].r-tree[p].l+1)*val; tree[p].mx+=val; return; } push_down(p);//将更改的信息往子树传递 int mid=(tree[p].l+tree[p].r)>>1; if(mid>=l)modify(tl(p),l,r,val);//如果区间与要修改的区间左边有交集,从左子树找 if(mid<r)modify(tr(p),l,r,val);//如果区间与要修改的区间右边有交集,从右子树找 push_up(p);//更新父亲 } ll query_sum(int p,int l,int r){ if(l<=tree[p].l&&r>=tree[p].r){//如果该区间刚好在要查询的区间中直接返回sum return tree[p].sum; } push_down(p);//遍历子树时,要将tag的信息往下传 int mid=(tree[p].l+tree[p].r)>>1; ll sum=0; if(mid>=l)sum+= query_sum(tl(p),l,r);//如果区间与要查询的区间左边有交集,从左子树找 if(mid<r)sum+= query_sum(tr(p),l,r);//如果区间与要查询的区间右边有交集,从右子树找 return sum;//返回答案 }
int main() { scanf("%d %d", &n, &m); for (int i = 1; i <= n; ++i) { scanf("%lld", &a[i]); } build(1, 1, n); while (m--) { int op, l, r, k; scanf("%d %d %d", &op, &l, &r); if (op == 1) { scanf("%d", &k); modify(1, l, r, k); } else { printf("%lld\n", query_sum(1, l, r)); } } return 0; }
|