1 solutions
-
1
聪明的人看这个讨论就已经不用往下看了。
题意
不多赘述。
主要是我不会概括思路
回想一下树状数组模板 2,我们既然可以用树状数组维护差分数组,那也可以用线段树维护差分数组。
把样例变成差分数组就是:
1 1 1 1 1 |1 2 3 4 5 ↓ | ↓ 1 2 3 3 -4|1 3 6 9 5
查询时再差前缀和就行了。
代码
不开龙龙见祖宗——hmz
#include <bits/stdc++.h> #define int long long using namespace std; const int N = 1e5 + 5; int n,m; int a[N],d[4 * N],b[4 * N]; void pd(int l,int r,int p){ int mid = l + (r - l >> 1); d[p * 2] += b[p] * (mid - l + 1),d[p * 2 + 1] += b[p] * (r - mid); b[p * 2] += b[p],b[p * 2 + 1] += b[p]; b[p] = 0; } void build(int l,int r,int p){ if (l == r){ // printf("%d:%d\n",l,p); d[p] = a[l]; return ; } int mid = l + (r - l >> 1); build(l,mid,p * 2); build(mid + 1,r,p * 2 + 1); d[p] = d[p * 2] + d[p * 2 + 1]; } void add(int tl,int tr,int x,int l,int r,int p){ if (tl <= l && r <= tr){ d[p] += x * (r - l + 1); b[p] += x; // printf("%d %d\n",p,d[p]); return ; } pd(l,r,p); int mid = l + (r - l >> 1); if (tl <= mid) add(tl,tr,x,l,mid,p * 2); if (mid < tr) add(tl,tr,x,mid + 1,r,p * 2 + 1); d[p] = d[p * 2] + d[p * 2 + 1]; // printf("%d %d\n",p,d[p]); } int query(int i,int l,int r,int p){ if (r <= i) return d[p]; pd(l,r,p); int mid = l + (r - l >> 1); int sum = query(i,l,mid,p * 2); if (mid < i) sum += query(i,mid + 1,r,p * 2 + 1); return sum; } void add(int tl,int tr,int k,int d){ add(tl,tl,k,1,n,1); if (tl < tr) add(tl + 1,tr,d,1,n,1); if (tr < n) add(tr + 1,tr + 1,-(k + d * (tr - tl)),1,n,1); } signed main(int argc, char **argv){ cin >> n >> m; for (int i = 1;i <= n;i++){ cin >> a[i]; } for (int i = n;i > 0;i--){ a[i] = a[i] - a[i - 1]; } build(1,n,1); while (m--){ int op; cin >> op; if (op == 1){ int l,r,k,d; cin >> l >> r >> k >> d; add(l,r,k,d); }else{ int p; cin >> p; printf("%lld\n",query(p,1,n,1)); } } return 0; }
- 1
Information
- ID
- 293
- Time
- 1000ms
- Memory
- 128MiB
- Difficulty
- 8
- Tags
- # Submissions
- 40
- Accepted
- 6
- Uploaded By