线段树维护差分

P1438 无聊的数列

思路:

线段树维护差分数组

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);
        }
    }
}
posted @ 2022-04-22 13:02  指引盗寇入太行  阅读(32)  评论(0编辑  收藏  举报