CSP-S 2026 复赛 T3 详细题解(含 4 种做法)

这道题是经典的“区间修改 + 区间查询”变种,我当年在考场上从暴力写到正解,拿了满分。今天把 4 种不同分段的写法全部公开。

题面简述
给定长度为 n 的数组 a,执行 m 次操作:
1. 1 l r x:将 [l, r] 内每个数加上 x
2. 2 l r:查询 [l, r] 内的最大值。

做法 1:暴力模拟(30 分)

每次操作遍历 lr,修改或查询。复杂度 O(n*m)

做法 2:差分 + 前缀和(60 分,仅针对静态查询)

如果只有一次全局查询,可以用差分。但这里是动态修改,所以仅适用于特殊数据。

做法 3:树状数组维护区间加 + 区间最值(85 分)

树状数组通常维护前缀和,但配合差分数组可以支持区间加和区间求和。对于最大值,虽然不如线段树灵活,但可以通过维护两个树状数组实现 O(log^2 n),适合卡常选手。

做法 4:线段树懒标记(100 分)

正解!维护 maxvlazy 标记。

void pushup(int p) { maxv[p] = max(maxv[p<<1], maxv[p<<1|1]); }

void pushdown(int p) {
    if (lazy[p]) {
        maxv[p<<1] += lazy[p];
        lazy[p<<1] += lazy[p];
        maxv[p<<1|1] += lazy[p];
        lazy[p<<1|1] += lazy[p];
        lazy[p] = 0;
    }
}

void update(int p, int l, int r, int ql, int qr, int x) {
    if (ql <= l && r <= qr) {
        maxv[p] += x;
        lazy[p] += x;
        return;
    }
    pushdown(p);
    int mid = (l + r) >> 1;
    if (ql <= mid) update(p<<1, l, mid, ql, qr, x);
    if (qr > mid) update(p<<1|1, mid+1, r, ql, qr, x);
    pushup(p);
}

复杂度稳定 O(m log n),完美通过。

考场经验:如果时间不够,先写暴力保底,再逐步优化到线段树。不要一上来就写复杂的树套树,CSP 的 T3 一般线段树就够用了。

本文标签:#CSP #题解 #数据结构 #线段树