题目链接
好感动,调了好久的一题终于调出来了
大体是线段树,pushup的地方稍微修改一下就好了
要注意的点是:线段树更新(pushup)的时候,需要用两个子结点重新计算父结点,不可以再保留原来的最大值了!这个点卡了很久很久
#include
using namespace std;
#define int long long
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
const int N = 5e5 + 10;
vector<int> a(N);
struct Node
{
// v:[l,r]中的合法答案
int l, r, sum, v;
}tr[N * 4];
void pushup(Node &u, Node &left, Node &right)
{
u.l = left.l, u.r = right.r;
u.sum = left.sum + right.sum;
u.v = max(left.v, max(left.sum + right.v, left.sum - a[right.l]));
}
void pushup(int u)
{
pushup(tr[u], tr[u << 1], tr[u << 1 | 1]);
}
void build(int u, int l, int r)
{
tr[u] = {l, r, 0, -0x3f3f3f3f3f3f3f3f};
if (l == r)
{
tr[u].sum = a[l];
return;
}
int mid = l + r >> 1;
build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
pushup(u);
}
void modify(int u, int pos, int x) // 把pos位置的值变成x
{
if (tr[u].l == pos && tr[u].r == pos)
{
tr[u].sum = x;
return;
}
int mid = tr[u].l + tr[u].r >> 1;
if (pos <= mid) modify(u << 1, pos, x);
else modify(u << 1 | 1, pos, x);
pushup(u);
}
Node query(int u, int l, int r)
{
if (tr[u].l >= l && tr[u].r <= r) return tr[u];
int mid = tr[u].l + tr[u].r >> 1;
if (r <= mid) return query(u << 1, l, r);
else if (l >= mid + 1) return query(u << 1 | 1, l, r);
else
{
auto left = query(u << 1, l, r);
auto right = query(u << 1 | 1, l, r);
Node res = {l, r, 0, -0x3f3f3f3f3f3f3f3f};
pushup(res, left, right);
return res;
}
}
void solve()
{
int n, q;
cin >> n >> q;
for (int i = 1; i <= n; i ++ ) cin >> a[i];
build(1, 1, n);
while (q -- )
{
int op, x, y;
cin >> op >> x >> y;
if (op == 1)
{
a[x] = y;
modify(1, x, y);
}
else
{
auto res = query(1, x, y);
cout << res.v << '\n';
}
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t -- )
{
solve();
}
}
题目链接
突然发现线段树好像也就那样,线段树最大的难点是在pushup
这里,其他都是板子罢了,主要是思维要清晰,能分清楚各种情况
#include
using namespace std;
#define int long long
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
const int N = 5e5 + 10;
const int inf = 0x3f3f3f3f3f3f3f3f;
vector<int> a(N);
struct Node
{
int l, r, sum;
int lmin, rmax; // 包含区间左端点的最小子段和和包含区间右端点的最大子段和
int ansl, ansr, ansall; // 包含区间左/右端点/整段区间的最大答案
int ans; // 整个区间最大答案
}tr[N * 4];
void pushup(Node &u, Node &left, Node &right)
{
u.l = left.l, u.r = right.r;
u.sum = left.sum + right.sum;
u.lmin = min(left.lmin, left.sum + right.lmin);
u.rmax = max(right.rmax, right.sum + left.rmax);
u.ansl = max({left.ansl, left.sum + right.ansl, left.sum - right.lmin, left.ansall - right.lmin});
u.ansr = max({right.ansr, left.ansr - right.sum, left.rmax - right.sum, left.rmax + right.ansall});
u.ansall = max({left.sum - right.sum, left.ansall - right.sum, left.sum + right.ansall});
u.ans = max({left.ans, right.ans, left.rmax - right.lmin, left.rmax + right.ansl, left.ansr - right.lmin});
}
void pushup(int u)
{
pushup(tr[u], tr[u << 1], tr[u << 1 | 1]);
}
void build(int u, int l, int r)
{
tr[u] = {l, r, 0, inf, -inf, -inf, -inf, -inf, -inf};
if (l == r)
{
tr[u].sum = tr[u].lmin = tr[u].rmax = a[l];
return;
}
int mid = l + r >> 1;
build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
pushup(u);
}
void modify(int u, int pos, int x) // 把pos位置的值变成x
{
if (tr[u].l == pos && tr[u].r == pos)
{
tr[u].sum = tr[u].lmin = tr[u].rmax = x;
return;
}
int mid = tr[u].l + tr[u].r >> 1;
if (pos <= mid) modify(u << 1, pos, x);
else modify(u << 1 | 1, pos, x);
pushup(u);
}
Node query(int u, int l, int r)
{
if (tr[u].l >= l && tr[u].r <= r) return tr[u];
int mid = tr[u].l + tr[u].r >> 1;
if (r <= mid) return query(u << 1, l, r);
else if (l >= mid + 1) return query(u << 1 | 1, l, r);
else
{
auto left = query(u << 1, l, r);
auto right = query(u << 1 | 1, l, r);
Node res = {l, r, 0, -inf};
pushup(res, left, right);
return res;
}
}
void solve()
{
int n, q;
cin >> n >> q;
for (int i = 1; i <= n; i ++ ) cin >> a[i];
build(1, 1, n);
while (q -- )
{
int op, x, y;
cin >> op >> x >> y;
if (op == 1)
{
a[x] = y;
modify(1, x, y);
}
else
{
auto res = query(1, x, y);
cout << res.ans << '\n';
}
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t -- )
{
solve();
}
}