线段树维护差分
思路:
线段树维护差分数组
code
#define ls(x) x<<1
#define rs(x) x<<1|1
struct tree {
int l, r;
int add, sum;
} tr[N << 2];
int a[N], b[N];
void pushup(tree& p, tree& l, tree& r) {
p.sum = l.sum + r.sum;
}
void pushdown(int u) {
tree& p = tr[u];
tree& left = tr[ls(u)];
tree& right = tr[rs(u)];
if (p.add) {
left.add += p.add;
right.add += p.add;
left.sum += (left.r - left.l + 1) * p.add;
right.sum += (right.r - right.l + 1) * p.add;
p.add = 0;
}
}
void pushup(int p) {
pushup(tr[p], tr[ls(p)], tr[rs(p)]);
}
void build(int p, int l, int r) {
if (l == r) tr[p] = { l, r, 0,b[l] };
else {
tr[p] = { l, r,0 };
int mid = l + r >> 1;
build(ls(p), l, mid), build(rs(p), mid + 1, r);
pushup(p);
}
}
void modify(int p, int l, int r, int d) {
if (tr[p].l >= l and tr[p].r <= r) {
tr[p].sum += (tr[p].r - tr[p].l + 1) * d;
tr[p].add += d;
}
else {//分裂
pushdown(p);
int mid = tr[p].l + tr[p].r >> 1;
if (l <= mid) modify(ls(p), l, r, d);
if (r > mid) modify(rs(p), l, r, d);
pushup(p);
}
}
tree query(int p, int l, int r) {
if (tr[p].l >= l and tr[p].r <= r) return tr[p];
else {
pushdown(p);//分裂
int mid = tr[p].l + tr[p].r >> 1;
if (r <= mid) return query(ls(p), l, r);
if (l > mid) return query(rs(p), l, r);
else {
auto left = query(ls(p), l, r);
auto right = query(rs(p), l, r);
tree ret;
pushup(ret, left, right);
return ret;
}
}
}
void D(int a[], int n) {
for (int i = 1;i <= n;i++) {
b[i]=a[i]-a[i-1];
}
}
void solve() {
int n = read(), m = read();
for (int i = 1;i <= n;i++) {
a[i] = read();
}
D(a, n);
build(1, 1, n + 5);
for (;m--;) {
int opt = read();
if (opt == 1) {
int l = read(), r = read(), k = read(), d = read();
modify(1, l, l, k);
modify(1, r + 1, r + 1, -k);
modify(1, l+1, r, d);
modify(1,r+1,r+1,-d*(r-l));
}
else {
int p = read();
printf("%lld\n", query(1, 1, p).sum);
}
}
}