关于线段树的疑惑
查看原帖
关于线段树的疑惑
671013
KawaragiMomoka楼主2023/7/22 18:31
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int maxn = 2e5 + 5;
int n, m, t;
struct SegmentTree {
    int left, right;
    int minv, tag;
    SegmentTree() : left(0), right(0), minv(0), tag(0) { }
} tree[maxn << 2];

inline void pushup(int root) {
    tree[root].minv = min(tree[root << 1].minv, tree[root << 1 | 1].minv);
}

inline void pushdown(int root) {
    if (!tree[root].tag) return;
    tree[root << 1].minv += tree[root].tag;
    tree[root << 1 | 1].minv += tree[root].tag;
    tree[root << 1].tag += tree[root].tag;
    tree[root << 1 | 1].tag += tree[root].tag;
    tree[root].tag = 0;
}

void build(int root, int l, int r) {
    tree[root].left = l;
    tree[root].right = r;
    if (l == r) {
        tree[root].minv = 0;
        tree[root].tag = 0;
        return;
    }
    int mid = (l + r) >> 1;
    build(root << 1, l, mid);
    build(root << 1 | 1, mid + 1, r);
    pushup(root);
}

// 单点修改
void solUpdate(int root, int pos) {
    if (tree[root].left == tree[root].right) {
        tree[root].minv++;
        tree[root].tag++; // 没有这一行就会错
        return;
    }
    pushdown(root);
    int mid = (tree[root].left + tree[root].right) >> 1;
    if (mid >= pos) solUpdate(root << 1, pos);
    else solUpdate(root << 1 | 1, pos);
    pushup(root);
}

// 区间修改
void mulUpdate(int root, int l, int r) {
    if (tree[root].left >= l && tree[root].right <= r) {
        tree[root].minv++;
        tree[root].tag++;
        return;
    }
    pushdown(root);
    int mid = (tree[root].left + tree[root].right) >> 1;
    if (mid >= l) mulUpdate(root << 1, l, r);
    if (mid < r) mulUpdate(root << 1 | 1, l, r);
    pushup(root);
}

int main() {
    scanf("%d", &t);
    while (t--) {
        bool edited = false;
        int ans;
        scanf("%d%d", &n, &m);
        fill(tree, tree + (n << 2), SegmentTree());
        build(1, 1, n);
        for (int i = 1; i <= m; i++) {
            int action, pos;
            scanf("%d%d", &action, &pos);
            if (edited) continue;
            if (action == 1) {
                solUpdate(1, pos);
            } else if (action == 2) {
                mulUpdate(1, 1, pos - 1);
                mulUpdate(1, pos + 1, n);
            }
            if (tree[1].minv > 0) {
                ans = i;
                edited = true;
            }
        }
        if (edited) printf("%d\n", ans);
        else printf("-1\n");
    }
    return 0;
}

代码如上,如果把注释标注出来的那一行删去就会错。 但是这是单点修改,把叶子节点打上懒标记又不会下传,为什么会错呢?

2023/7/22 18:31
加载中...