题目背景
无聊的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
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;
}