1 条题解
-
0
写这篇题解主要是为了记录一个小技巧:
区间加一个等差数列,可以用差分:
设差分序列为 ,首项为 ,末项为 ,公差为 ,要在 这段区间加上这个等差数列。
在 加上 ,在 加上 ,最后在 减去 即可。
在这道题中,可以用线段树维护这个差分序列,求第 个数是多少时,答案就是 。
以及,小心越界,开 longlong。
#include <bits/stdc++.h> using namespace std; int n, m; long long a[100005], tree[400005], lazy[400005]; void pushdown(int rt, int l, int r) { int m = (l+r)>>1; tree[rt<<1] += (m-l+1)*lazy[rt]; tree[rt<<1|1] += (r-m)*lazy[rt]; lazy[rt<<1] += lazy[rt]; lazy[rt<<1|1] += lazy[rt]; lazy[rt] = 0; } void build(int rt, int l = 1, int r = n) { if (l == r) { tree[rt] = a[l]-a[l-1]; return; } int m = (l+r)>>1; build(rt<<1, l, m); build(rt<<1|1, m+1, r); tree[rt] = tree[rt<<1]+tree[rt<<1|1]; } long long query(int rt, int x, int y, int l = 1, int r = n) { if (l >= x && r <= y) return tree[rt]; pushdown(rt, l, r); int m = (l+r)>>1; long long ans = 0; if (x <= m) ans += query(rt<<1, x, y, l, m); if (m < y) ans += query(rt<<1|1, x, y, m+1, r); return ans; } void modify(int rt, long long val, int x, int y, int l = 1, int r = n) { if (l >= x && r <= y) { tree[rt] += (r-l+1)*val; lazy[rt] += val; return ; } pushdown(rt, l, r); int m = (l+r)>>1; if (x <= m) modify(rt<<1, val, x, y, l, m); if (m < y) modify(rt<<1|1, val, x, y, m+1, r); tree[rt] = tree[rt<<1]+tree[rt<<1|1]; } int main() { cin >> n >> m; for (int i = 1; i <= n; i++) cin >> a[i]; build(1); while (m--) { int opt; cin >> opt; if (opt == 1) { int l, r; long long K, D; cin >> l >> r >> K >> D; modify(1, K, l, l); if (l+1 <= n) modify(1, D, l+1, r); if (r+1 <= n) modify(1, -(K+(r-l)*D), r+1, r+1); } else { int p; cin >> p; cout << query(1, 1, p) << endl; } } return 0; }
- 1
信息
- ID
- 438
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 4
- 标签
- 递交数
- 15
- 已通过
- 2
- 上传者