
题目描述
如题,已知一个数列,你需要进行下面两种操作:
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<iostream>
2 #include<cstdio>
3 #define ll long long
4 using namespace std;
5 const ll N=100002;
6 ll n,a[N],m,add[N*10],sum[N*10];
7 void build(ll o,ll l,ll r)
8 {
9 if(l==r)
10 {
11 sum[o]=a[l];
12 return;
13 }
14 ll mid=(l+r)>>1;
15 build(o<<1,l,mid);
16 build(o<<1|1,mid+1,r);
17 sum[o]=sum[o<<1]+sum[o<<1|1];
18 }
19 ll op,x,y,k;
20 void down(ll o,ll l,ll r,ll mid)
21 {
22 if(add[o])
23 {
24 add[o<<1]+=add[o];
25 sum[o<<1]+=add[o]*(mid-l+1);
26
27 add[o<<1|1]+=add[o];
28 sum[o<<1|1]+=add[o]*(r-(mid+1)+1);
29
30 add[o]=0;
31 }
32 }
33 void up(ll o,ll l,ll r,ll x,ll y,ll k)
34 {
35 if(x<=l && y>=r)
36 {
37 add[o]+=k;
38 sum[o]+=k*(r-l+1);
39 return;
40 }
41 ll mid=(l+r)>>1;
42 down(o,l,r,mid);
43 if(x<=mid)up(o<<1,l,mid,x,y,k);
44 if(y>=mid+1)up(o<<1|1,mid+1,r,x,y,k);
45 sum[o]=sum[o<<1]+sum[o<<1|1];
46 }
47 ll query(ll o,ll l,ll r,ll x,ll y)
48 {
49 if(x<=l && y>=r)
50 {
51 down(o,l,r,(l+r)>>1);
52 return sum[o];
53 }
54 ll mid=(l+r)>>1;
55 down(o,l,r,mid);
56 ll tot=0;
57 if(x<=mid)tot+=query(o<<1,l,mid,x,y);
58 if(y>mid)tot+=query(o<<1|1,mid+1,r,x,y);
59 return tot;
60 }
61 int main()
62 {
63 scanf("%lld%lld",&n,&m);
64 for(ll i=1;i<=n;i++) scanf("%d",&a[i]);
65 build(1,1,n);
66 while(m--)
67 {
68 scanf("%lld%lld%lld",&op,&x,&y);
69 if(op==1)
70 {
71 scanf("%lld",&k);
72 up(1,1,n,x,y,k);
73 }else{
74 printf("%lld
",query(1,1,n,x,y));
75 }
76 }
77 return 0;
78 }