1. 程式人生 > >Luogu P3372【模板】線段樹 1

Luogu P3372【模板】線段樹 1

輸入 clas chan ons 復制 change 初始 兩個 所有

題目描述

如題,已知一個數列,你需要進行下面兩種操作:

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 }

Luogu P3372【模板】線段樹 1