P4513 小白逛公园

P4513 小白逛公园

题意

给定一个序列 \(A\),你需要支持以下操作:

  • 单点修改

  • 查询区间 \([l,r]\) 的最大子段和

\(1 \leq n \leq 5 \times 10^{5}\)\(1 \leq m \leq 10^{5}\)

题解

单点修改,查询区间信息,于是想到线段树。

发现最大子段的位置只有 \(3\) 种:

  • 横穿左区间和右区间

  • 左区间中

  • 右区间中

所以我们使用线段树记录:

  • 这个区间从左端点开始的最大子段 \(Lmax\)

  • 这个区间从右端点开始的最大子段 \(Rmax\)

  • 无限制的最大子段 \(Tmax\)

为了方便转移,我们再记录区间和 \(Sum\)

在合并的时候,分类讨论取最值即可。

对于询问,合并所有包含的线段,输出 \(Tmax\) 即可。

实现

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define lson (u << 1)
#define rson (u << 1 | 1)
#define Mid (r + l >> 1)
signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n, m;
    cin >> n >> m;
    vector<int> Lmax((n << 2) + 100);
    vector<int> Rmax((n << 2) + 100);
    vector<int> Tmax((n << 2) + 100);
    vector<int> Sum((n << 2) + 100);
    function<array<int, 4>(int, int, int, int, int, int, int, int)> f =
        [&](int S1, int T1, int L1, int R1, int S2, int T2, int L2,
            int R2) -> array<int, 4> {
        // 更新 Sum
        int S = S1 + S2;
        // 更新 Tmax
        int T = INT_MIN;       // 一个不取
        T = max(T, R1 + L2);   // 从中间穿过
        T = max({T, T1, T2});  // 不穿过
        // 更新 Rmax
        int R = INT_MIN;      // 一个不取
        R = max(R, R2);       // 取右边
        R = max(R, S2 + R1);  // 穿过
        // 更新 Lmax
        int L = INT_MIN;      // 一个不取
        L = max(L, L1);       // 取左边
        L = max(L, S1 + L2);  // 穿过
        return {S, T, L, R};
    };
    function<void(int)> merge = [&](int u) -> void {
        array<int, 4> nxt = f(Sum[lson], Tmax[lson], Lmax[lson], Rmax[lson],
                              Sum[rson], Tmax[rson], Lmax[rson], Rmax[rson]);
        Sum[u] = nxt[0];
        Tmax[u] = nxt[1];
        Lmax[u] = nxt[2];
        Rmax[u] = nxt[3];
    };
    function<void(int, int, int, int, int)> update = [&](int u, int l, int r,
                                                         int i, int k) -> void {
        int L = i;
        int R = i;
        if (L <= l && r <= R) {
            Lmax[u] = k;
            Rmax[u] = k;
            Tmax[u] = k;
            Sum[u] = k;
            return;
        }
        if (L <= Mid) update(lson, l, Mid, i, k);
        if (R > Mid) update(rson, Mid + 1, r, i, k);
        merge(u);
    };
    function<array<int, 4>(int, int, int, int, int)> query =
        [&](int u, int l, int r, int L, int R) -> array<int, 4> {
        array<int, 4> ans;
        if (L <= l && r <= R) {
            ans[0] = Sum[u];
            ans[1] = Tmax[u];
            ans[2] = Lmax[u];
            ans[3] = Rmax[u];
            return ans;
        }
        array<int, 4> ansL;
        array<int, 4> ansR;
        bool isL = 0;
        bool isR = 0;
        if (L <= Mid) {
            ansL = query(lson, l, Mid, L, R);
            isL = 1;
        }
        if (R > Mid) {
            ansR = query(rson, Mid + 1, r, L, R);
            isR = 1;
        }
        if (isL && isR) {
            ans = f(ansL[0], ansL[1], ansL[2], ansL[3], ansR[0], ansR[1],
                    ansR[2], ansR[3]);
        } else if (isL) {
            ans = ansL;
        } else {
            ans = ansR;
        }
        return ans;
    };
    for (int i = 1; i <= n; i++) {
        int x;
        cin >> x;
        update(1, 1, n, i, x);
    }
    while (m--) {
        int k;
        cin >> k;
        if (k == 1) {
            int a, b;
            cin >> a >> b;
            cout << query(1, 1, n, min(a, b), max(a, b))[1] << '\n';
        } else {
            int p, s;
            cin >> p >> s;
            update(1, 1, n, p, s);
        }
    }
}
posted @ 2026-08-06 14:57  曼波绿豆哈基蜂  阅读(1)  评论(0)    收藏  举报