题目描述
如题,已知一个数列,你需要进行下面两种操作:
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 #include2 #include <string.h> 3 #include 4 #include 5 #include <string> 6 #include 7 #include 8 #include 9 #include <string.h> 10 #include 11 #include 12 #include <set> 13 #define l(rt) rt<<1 14 #define r(rt) (rt<<1)+1 15 16 using namespace std; 17 const int maxn = 100005; 18 int n, m; 19 struct node { 20 int l, r; 21 long long sum,inc; 22 }tree[maxn<<3]; 23 24 void build(int rt,int l,int r) { 25 tree[rt].l = l, tree[rt].r = r; 26 tree[rt].sum = tree[rt].inc = 0; 27 if (l == r)return; 28 int mid = (l + r) / 2; 29 build(l(rt), l, mid); 30 build(r(rt), mid + 1, r); 31 } 32 33 void change(int rt,int l,int r,long inc) { 34 if (tree[rt].l == l && tree[rt].r == r) { 35 tree[rt].inc += inc; 36 return; 37 } 38 tree[rt].sum += inc * (r - l + 1); 39 int mid = (tree[rt].l + tree[rt].r) / 2; 40 if (l >= mid + 1) 41 change(r(rt), l, r,inc); 42 else if (r <= mid) 43 change(l(rt), l, r,inc); 44 else { 45 change(l(rt), l, mid,inc); 46 change(r(rt), mid+1, r,inc); 47 } 48 } 49 50 long long query(int rt,int l, int r) { 51 if (tree[rt].l == l && tree[rt].r == r) { 52 tree[rt].sum += tree[rt].inc * (tree[rt].r - tree[rt].l + 1); 53 tree[r(rt)].inc += tree[rt].inc; 54 tree[l(rt)].inc += tree[rt].inc; 55 tree[rt].inc = 0; 56 return tree[rt].sum; 57 } 58 tree[rt].sum += tree[rt].inc * (tree[rt].r-tree[rt].l+1); 59 tree[r(rt)].inc += tree[rt].inc; 60 tree[l(rt)].inc += tree[rt].inc; 61 tree[rt].inc = 0; 62 int mid = (tree[rt].l + tree[rt].r) / 2; 63 if (l > mid) 64 return query(r(rt), l, r); 65 else if (r <= mid) 66 return query(l(rt), l, r); 67 else 68 return query(l(rt), l, mid) + query(r(rt), mid + 1, r); 69 } 70 71 void init() { 72 scanf("%d%d", &n, &m); 73 build(1, 1, n); 74 for (int i = 1; i <= n; i++) { 75 int x; 76 scanf("%d", &x); 77 change(1, i, i, x); 78 } 79 while (m--) { 80 int oper; 81 scanf("%d", &oper); 82 if (oper == 1) { 83 int x, y, k; 84 scanf("%d%d%d", &x, &y, &k); 85 change(1, x, y, k); 86 } 87 else if (oper == 2) { 88 int x, y; 89 scanf("%d%d", &x, &y); 90 long long ans = query(1,x, y); 91 printf("%lld\n", ans); 92 } 93 } 94 } 95 96 int main() 97 { 98 init(); 99 return 0; 100 }
是上课时的例题
因为睡着了所以做一遍
WA点:
一开始把 query() 函数中更新 tree[rt].sum 的值时 tree[rt].inc 乘上的值写成了 r-l+1 ,显然是错误的……手误
貌似 r(rt) 的表达式中必须加括号
大致思路:延迟更新,避免TLE