题目背景
无聊的YYB总喜欢搞出一些正常人无法搞出的东西。有一天,无聊的YYB想出了一道无聊的题:无聊的数列。。。(K峰:这题不是傻X题吗)
题目描述
维护一个数列{a[i]},支持两种操作:
1、1 L R K D:给出一个长度等于R-L+1的等差数列,首项为K,公差为D,并将它对应加到a[L]~a[R]的每一个数上。即:令a[L]=a[L]+K,a[L+1]=a[L+1]+K+D,
a[L+2]=a[L+2]+K+2D……a[R]=a[R]+K+(R-L)D。
2、2 P:询问序列的第P个数的值a[P]。
输入输出格式
输入格式:
第一行两个整数数n,m,表示数列长度和操作个数。
第二行n个整数,第i个数表示a[i](i=1,2,3…,n)。
接下来的m行,表示m个操作,有两种形式:
1 L R K D
扫描二维码关注公众号,回复:
1550289 查看本文章
2 P 字母意义见描述(L≤R)。
输出格式:
对于每个询问,输出答案,每个答案占一行。
输入输出样例
说明
数据规模:
0≤n,m≤100000
|a[i]|,|K|,|D|≤200
Hint:
有没有巧妙的做法?
总结:线段树来做
考虑维护差分数组
a[l....r] 加上一个公差为d, 首项为k的等差数列
则相当于差分数组
1. c[l] += k, c[r + 1] -= k
2. c[i] += d (l + 1 <= i <= r)
3. c[r + 1] -= (r - l) * d
第一个好理解吧, 每个数都加了k
第二个,相当于每一项加的都比前一项多加d
第三项,相当于a[r] 加了 (r - l) * d,而 a[r + 1]没变
注意边界问题
#include <bits/stdc++.h> using namespace std; const int maxn = 4e5 + 7; int n, m, a[maxn], sum[maxn], laz[maxn], val[maxn]; void update(int o) { val[o] = val[o << 1] + val[o << 1 | 1]; } void pushdown(int o, int l, int r) { if(laz[o] != 0) { int mid = (l + r) >> 1; laz[o << 1] += laz[o]; laz[o << 1 | 1] += laz[o]; val[o << 1] += (mid - l + 1) * laz[o]; val[o << 1 | 1] += (r - mid) * laz[o]; laz[o] = 0; } } void build(int o, int l, int r) { if(l == r) { val[o] = sum[l]; return; } int mid = (l + r) >> 1; build(o << 1, l, mid); build(o << 1 | 1, mid + 1, r); update(o); } void modify(int o, int l, int r, int ql, int qr, int z) { if(ql <= l && r <= qr) { val[o] += (r - l + 1) * z; laz[o] += z; return; } int mid = (l + r) >> 1; pushdown(o, l, r); if(ql <= mid) modify(o << 1, l, mid, ql, qr, z); if(qr > mid) modify(o << 1 | 1, mid + 1, r, ql, qr, z); update(o); } int query(int o, int l, int r, int ql, int qr) { if(ql <= l && r <= qr) return val[o]; int res = 0, mid = (l + r) >> 1; pushdown(o, l, r); if(ql <= mid) res += query(o << 1, l, mid, ql, qr); if(qr > mid) res += query(o << 1 | 1, mid + 1, r, ql, qr); return res; } int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; ++i) scanf("%d", &a[i]), sum[i] = a[i] - a[i - 1]; build(1, 1, n); while(m--) { int opt, l, r, k, d, p; scanf("%d", &opt); if(opt == 1) { scanf("%d%d%d%d", &l, &r, &k, &d); if(r < n) modify(1, 1, n, r + 1, r + 1, -(k + d * (r - l))); modify(1, 1, n, l, l, k); if(l < r) modify(1, 1, n, l + 1, r, d); } else scanf("%d", &p), printf("%d\n", query(1, 1, n, 1, p)); } return 0; }