Luogu P1438無聊的數列
阿新 • • 發佈:2021-08-15
題目連結
題目描述
維護一個數列\(a_i\),支援兩種操作:
- 給出一個長度等於 \(r-l+1\)的等差數列,首項為\(k\) 公差為\(d\) 並將它對應加到\([l,r]\)範圍中的每一個數上。
即:令\(a_l=a_l+k\) \(a_{l+1}=a_{l+1}+k+d\) ... \(a_r = a_r + k + (r-l) * d\) 。- 詢問數列的第\(p\)個數的值\(a_p\).
解題思路
我們可以通過等差數列的性質\(a_i - a_{i-1} = d\)聯想到我們可以用差分解決這道題目
我們先定義一個差分陣列d[]
將等差數列的每一項都加到\([l,r]\)範圍中的每一個數上
等價於 \(d_l\) +k
\(d_i(l<i<r+1)\) +d
\(d_{r+1}\) -k + (r-l)*d
對於第二個操作,我們對差分陣列求一遍字首和就可以了
因此本題就是一個線段樹的模板題
AC_CODE
#include <bits/stdc++.h> #define rep(i, a, b) for(int i = a; i <= b; i ++ ) using namespace std; typedef long long LL; const int N = 1e5 + 10; int n, m; int arr[N], a[N]; struct Node { int l, r; LL val, add; }tr[N * 4]; void pushup(int u) { tr[u].val = tr[u << 1].val + tr[u << 1 | 1].val; } void pushdown(int u) { Node &root = tr[u], &ls = tr[u << 1], &rs = tr[u << 1 | 1]; ls.add += root.add, ls.val += 1LL * root.add * (ls.r - ls.l + 1); rs.add += root.add, rs.val += 1LL * root.add * (rs.r - rs.l + 1); root.add = 0; } void build(int u, int l, int r) { if(l == r) { tr[u] = {l, r, a[l]}; } else { tr[u] = {l, r}; int mid = l + r >> 1; build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r); pushup(u); } } void update(int u, int l, int r, int d) { if(tr[u].l >= l && tr[u].r <= r) { tr[u].add += d; tr[u].val += 1LL * (tr[u].r - tr[u].l + 1) * d; } else { pushdown(u); int mid = tr[u].l + tr[u].r >> 1; if(l <= mid) update(u << 1, l, r, d); if(r > mid) update(u << 1 | 1, l, r, d); pushup(u); } } LL query(int u, int l, int r) { if(tr[u].l >= l && tr[u].r <= r) { return tr[u].val; } else { pushdown(u); int mid = tr[u].l + tr[u].r >> 1; LL res = 0; if(l <= mid) res = query(u << 1, l, r); if(r > mid) res += query(u << 1 | 1, l, r); return res; } } void solve() { cin >> n >> m; for(int i = 1; i <= n; i ++ ) { cin >> arr[i]; a[i] = arr[i] - arr[i - 1]; } build(1, 1, n); int op, l, r, d, k; while(m -- ) { cin >> op; if(op == 1) { cin >> l >> r >> k >> d; update(1, l, l, k); if(l < r) //注意邊界 (被卡了一個多小時 update(1, l + 1, r, d); int p = 0 - k - (r - l) * d; if(r != n) //同上 qwq update(1, r + 1, r + 1, p); } else { scanf("%d", &k); printf("%lld\n", query(1, 1, k)); } } } signed main() { solve(); return 0; }