【题目描述】:

如题,已知一个数列,你需要进行下面两种操作:

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的结果。

【样例输入】:

5 5
1 5 4 2 3
2 2 4
1 2 3 2
2 3 4
1 1 5 1
2 1 4

【样例输出】:

11
8
20

【时间限制、数据范围及描述】:

时间:1s 空间:128M

对于30%的数据:N<=8,M<=10

对于70%的数据:N<=1000,M<=10000

对于100%的数据:N<=100000,M<=100000

(数据保证在int64/long long数据范围内)

 

感觉通过加和乘那一题,我的线段树水平有了质的提升,还是那个原则,打延迟标记的时候当前节点也要更新,并且,只要需要访问子节点,就一定要标记下传,无论是查询还是更新!!!

 

1 #include "bits/stdc++.h"
2 #define mem(a,b) memset(a,b,sizeof(a))
3 #define lson rt<<1,l,m
4 #define rson rt<<1|1,m+1,r
5 using namespace std;
6 typedef long long LL;
7 const int MAX=100005;
8 int n,m;
9 LL sum[MAX*4],la[MAX*4];
10 void PushUp(int rt){
11 sum[rt]=sum[rt<<1]+sum[rt<<1|1];
12 }
13 void PushDown(int rt,int l,int r){
14 int m=(l+r)>>1;
15 if (la[rt]!=0){
16 la[rt<<1]+=la[rt];la[rt<<1|1]+=la[rt];
17 sum[rt<<1]+=la[rt]*(m-l+1);sum[rt<<1|1]+=la[rt]*(r-m);
18 la[rt]=0;
19 }
20 }
21 void build(int rt,int l,int r){
22 if (l==r){
23 scanf("%lld",&sum[rt]);
24 la[rt]=0;
25 return;
26 }la[rt]=0;
27 int m=(l+r)>>1;
28 build(lson);
29 build(rson);
30 PushUp(rt);
31 }
32 void update(int rt,int l,int r,LL x,LL y,LL z){
33 if (x<=l && r<=y){
34 la[rt]+=z;
35 sum[rt]+=(r-l+1)*z;
36 return;
37 }
38 int m=(l+r)>>1;
39 PushDown(rt,l,r);
40 if (x<=m)
41 update(lson,x,y,z);
42 if (y>m)
43 update(rson,x,y,z);
44 PushUp(rt);
45 }
46 LL search(int rt,int l,int r,int x,int y){
47 if (x<=l && r<=y) return sum[rt];
48 LL an=0;
49 int m=(l+r)>>1;
50 PushDown(rt,l,r);
51 if (x<=m)
52 an+=search(lson,x,y);
53 if (y>m)
54 an+=search(rson,x,y);
55 return an;
56 }
57 int main(){
58 freopen ("segtree.in","r",stdin);
59 freopen ("segtree.out","w",stdout);
60 int i,j;
61 LL x,y,z,w;
62 scanf("%d%d",&n,&m);
63 build(1,1,n);
64 for (i=1;i<=m;i++){
65 scanf("%lld",&w);
66 if (w==1){
67 scanf("%lld%lld%lld",&x,&y,&z);
68 update(1,1,n,x,y,z);
69 }
70 if (w==2){
71 scanf("%lld%lld",&x,&y);
72 printf("%lld\n",search(1,1,n,x,y));
73 }
74 }
75 return 0;
76