Luogu P3372【模板】線段樹 1
阿新 • • 發佈:2018-02-22
輸入 clas chan ons 復制 change 初始 兩個 所有
輸出樣例#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
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 7const 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