Luogu 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数据范围内)

 

注意long long

 1 //2018年2月22日21:12:39
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cstring>
 5 using namespace std;
 6 
 7 const int N = 1000000;
 8 int n, m;
 9 long long a[N];
10 long long A[N<<2], sum[N<<1], size[N<<1];
11 
12 void change(int k1){
13     sum[k1] = sum[k1*2] + sum[k1*2+1]; 
14 }
15 
16 void buildtree(int k1, int l, int r){
17     size[k1] = r-l+1;
18     if(l == r){
19         sum[k1] = a[l];
20         return;
21     }
22     int mid = l+r >> 1;
23     buildtree(k1*2, l, mid);
24     buildtree(k1*2+1, mid+1, r);
25     change(k1); 
26 }
27 
28 void add(int k1, int x){
29     A[k1] += x;
30     sum[k1] = sum[k1] + size[k1]*x;
31 }
32 void pushdown(int k1){
33     if(A[k1]){
34         add(k1*2, A[k1]);
35         add(k1*2+1, A[k1]);
36         A[k1] = 0;
37     }
38 }
39 
40 void addall(int k1, int l, int r, int L, int R, int x){
41     if(l>R || r<L) return;
42     if(l>=L && r<=R){
43         add(k1, x);
44         return;
45     }
46     int mid = l+r >> 1;
47     pushdown(k1);
48     addall(k1*2, l, mid, L, R, x);
49     addall(k1*2+1, mid+1, r, L, R, x);
50     change(k1);
51 }
52 
53 long long find(int k1, int l, int r, int L, int R){
54     if(l>R || r<L) return 0;
55     if(l>=L && r<=R) return sum[k1];
56     int mid = l+r >> 1;
57     pushdown(k1);
58     return (find(k1*2, l, mid, L, R) + find(k1*2+1, mid+1, r, L, R));
59 }
60 
61 int main(){
62     scanf("%d%d", &n, &m);
63     for(int i=1;i<=n;i++)
64         scanf("%lld", &a[i]);
65     buildtree(1, 1, n);
66     for(int i=1;i<=m;i++){
67         int k1, k2, k3;
68         scanf("%d%d%d", &k1, &k2, &k3);
69         if(k1 == 1){
70             long long k4;
71             scanf("%lld", &k4);
72             addall(1, 1, n, k2, k3, k4);
73         }else if(k1 == 2){
74             printf("%lld\n", find(1, 1, n, k2, k3));
75         }
76     }
77 
78     return 0;
79 }

 

posted @ 2018-02-22 21:50  sinEagle  阅读(167)  评论(0编辑  收藏  举报