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);
}
}
}
浙公网安备 33010602011771号