线段树求调,悬关

P3372 【模板】线段树 1

残阳如血 @ 2023-10-03 21:00:11

悬 2 关!

#include <iostream>
const int MAX = 1e5 + 10;
typedef long long lint;

lint a[MAX], w[4 * MAX], lzy[4 * MAX];

void pushup(const int u) {
    w[u] = w[u * 2] + w[u * 2 + 1];
}

void maketag(const int u, int len, lint x) {
    lzy[u] += x, w[u] += len * x;
}

void pushdown(const int u, int l, int r) {
    int mid = (l + r) / 2;
    maketag(u * 2, l, mid);
    maketag(u * 2 + 1, mid + 1, r);
    lzy[u] = 0;
}

void build(const int u, int l, int r) {
    if (l == r) {
        w[u] = a[l];
        return ;
    }
    int mid = (l + r) / 2;
    build(u * 2, l, mid);
    build(u * 2 + 1, mid + 1, r);
    pushup(u);
}

lint queryNode(const int u, int l, int r, int p) {
    if (l == r) return w[u];
    int mid = (l + r) / 2;
    pushdown(u, l, r);
    if (mid >= p) return queryNode(u * 2, l, mid, p);
    else return queryNode(u * 2 + 1, mid + 1, r, p);
}

void updateNode(const int u, int l, int r, int p, lint x) {
    if (l == r) {
        w[u] = x;
        return ;
    }
    int mid = (l + r) / 2;
    pushdown(u, l, r);
    updateNode(u * 2, l, mid, p, x);
    updateNode(u * 2 + 1, mid + 1, r, p, x);
    pushup(u);
}

lint query(const int u, int l, int r, int tarl, int tarr) {
    if (tarl > r || tarr < l) return 0;
    if (tarl >= l && tarr <= r) return w[u];
    int mid = (l + r) / 2;
    pushdown(u, l, r);
    return query(u * 2, l, mid, tarl, tarr) + query(u * 2 + 1, mid + 1, r, tarl, tarr);
}

void update(const int u, int l, int r, int tarl, int tarr, lint x) {
    if (tarl > r || tarr < l) return ;
    if (tarl >= l && tarr <= r) {
        maketag(u, r - l + 1, x);
        return ;
    }
    int mid = (l + r) / 2;
    pushdown(u, l, r);
    update(u * 2, l, mid, tarl, tarr, x);
    update(u * 2 + 1, mid + 1, r, tarl, tarr, x);
    pushup(u);
}

int main() {
    int n, m; std::cin >> n >> m;
    for (int i = 1; i <= n; ++i) std::cin >> a[i];
    build(1, 1, n);
    for (lint op, x, y, k; m; --m) {
        std::cin >> op >> x >> y;
        if (op == 1) std::cin >> k, update(1, 1, n, x, y, k);
        else std::cout << query(1, 1, n, x, y) << '\n';
    }
    return 0;
}

by xiaofu15191 @ 2023-10-03 21:03:08

显然你pushdown的时候不该调用maketag 不然就是参数写错了


by xiaofu15191 @ 2023-10-03 21:04:07

正常pushdown长这样:

void push_down(int now,int l,int r)
{
    int mid=(l+r)/2;
    tree[now*2]+=lazy[now]*(mid-l+1);
    lazy[now*2]+=lazy[now];
    tree[now*2+1]+=lazy[now]*(r-mid);
    lazy[now*2+1]+=lazy[now];
    lazy[now]=0;
}

by xiaofu15191 @ 2023-10-03 21:06:44

你理解的似乎不太透彻(


by 大眼仔Happy @ 2023-10-03 21:07:34

@xiaofu15191 显然是参数写错了,pushdown调用maketag不是因为懒得写那么多吗(个人习惯)


by xiaofu15191 @ 2023-10-03 21:09:04

@大眼仔Happy 就是参数写错了 口误了(


by xiaofu15191 @ 2023-10-03 21:09:35

@残阳如血


|