洛谷P3372 【模板】线段树 1(线段树+区间加+区间求和)

题目描述

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

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

输入输出样例

输入 #1
5 5
1 5 4 2 3
2 2 4
1 2 3 2
2 3 4
1 1 5 1
2 1 4
输出 #1
11
8
20

说明/提示

时空限制:1000ms,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 using namespace std;
 3 typedef long long ll;
 4 
 5 const ll MAXN=100000+5;
 6 ll st[MAXN<<2],lazy[MAXN<<2];///lazy懒标记数组
 7 ll n,m;
 8 
 9 void pushup(ll rt)
10 {
11     st[rt]=st[rt<<1]+st[rt<<1|1];
12 }
13 void pushdown(ll l,ll r,ll rt)
14 {
15     if(lazy[rt]==0)return;
16     lazy[rt<<1]+=lazy[rt];
17     lazy[rt<<1|1]+=lazy[rt];
18     ll mid=(l+r)>>1;
19     st[rt<<1]+=lazy[rt]*(mid-l+1);
20     st[rt<<1|1]+=lazy[rt]*(r-mid);
21     lazy[rt]=0;
22 }
23 void build(ll l,ll r,ll rt)
24 {
25     lazy[rt]=0;
26     if(l==r)
27     {
28         st[rt]=0;
29         return;
30     }
31     ll mid=(l+r)>>1;
32     pushdown(l,r,rt);
33     build(l,mid,rt<<1);
34     build(mid+1,r,rt<<1|1);
35     pushup(rt);
36 }
37 void update(ll L,ll R,ll val,ll l,ll r,ll rt)
38 {
39     if(L<=l&&r<=R)
40     {
41         lazy[rt]+=val;
42         st[rt]+=(r-l+1)*val;
43         return;
44     }
45     pushdown(l,r,rt);
46     ll mid=(l+r)>>1;
47     if(L<=mid)update(L,R,val,l,mid,rt<<1);
48     if(R>mid)update(L,R,val,mid+1,r,rt<<1|1);
49     pushup(rt);
50 }
51 ll query(ll L,ll R,ll l,ll r,ll rt)
52 {
53     if(L<=l&&r<=R)return st[rt];
54     pushdown(l,r,rt);
55     ll mid=(l+r)>>1,res=0;
56     if(L<=mid)res+=query(L,R,l,mid,rt<<1);
57     if(R>mid)res+=query(L,R,mid+1,r,rt<<1|1);
58     pushup(rt);
59     return res;
60 }
61 int main()
62 {
63     ll x,y,v,op;
64     scanf("%lld%lld",&n,&m);
65     build(1,n,1);
66     for(ll i=1; i<=n; i++)
67     {
68         scanf("%lld",&x);
69         update(i,i,x,1,n,1);
70     }
71     for(ll i=1; i<=m; i++)
72     {
73         scanf("%lld",&op);
74         if(op==1)
75         {
76             scanf("%lld%lld%lld",&x,&y,&v);
77             update(x,y,v,1,n,1);
78         }
79         else if(op==2)
80         {
81             scanf("%lld%lld",&x,&y);
82             printf("%lld\n",query(x,y,1,n,1));
83         }
84     }
85 }

 

posted @ 2019-11-15 20:23  Cherlie  阅读(213)  评论(0编辑  收藏  举报