Daimayuan Online Judge 线段树2

n 个数 a1,a2,,an
支持 q 个操作:

  1. 1 x d ,修改 ax=d
  2. 2 l r ,查询 [l,r] 中的最大子段和。

一:确定需要维护的信息。根据分治中线讨论,哪些信息可以合并出所需信息。递归讨论新信息如何合并。直至完全拆解。

  1. 不越过分治中线:[l,r] 的最大子段和,要么是 [l,mid] 的最大子段和,要么是 [mid+1,r] 的最大子段和。
  2. 越过分治中线:[l,mid] 的最大后缀和 + [mid+1,r] 的最大前缀和。
  3. 递归讨论 [l,r] 的最大后缀和最大前缀如何维护:
    1. 不越过分治中线:[l,r] 的最大后缀和为 [mid+1,r] 的最大后缀和;[l,r] 的最大前缀和为 [l,mid] 的最大前缀和。
    2. 越过分治中线:[l,r] 的最大后缀和为 [l,mid] 的最大后缀和 + [mid+1,r] 的和;[l,r] 的最大前缀和为 [mid+1,r] 的最大前缀和 + [l,mid] 的和。
    3. 递归讨论 [l,r] 的和如何维护:
      1. [l,r] 的和显然越过分治中线,为 [l,mid+1] 的和 + [mid+1,r] 的和。不再产生新信息。
  4. 补充: update[l,r] 信息与 [l,mid][mid+1,r] 的信息独立,不需要考虑 [l,r] 信息更新的顺序。
struct Info {
long long mss, mpre, msuf, s; // 最大子段和,最大前缀和,最大后缀和,区间和
};
struct Node {
Info f;
} seg[N * 4];
Info operator + (const Info &l, const Info &r) {
Info ret;
ret.mss = std::max({l.mss, r.mss, l.sufs + r.pres});
ret.pres = std::max(l.mpre, l.s + r.mpre);
ret.sufs = std::max(r.msuf, l.msuf + r.s);
ret.s = l.s + r.s;
return ret;
}
void update(int id) {
seg[id].f = seg[ id * 2 ].f + seg[ id * 2 + 1 ].f;
}

二:完成主程序框架

int main() {
int n, q;
std::cin >> n >> q;
for (int i = 1; i <= n; i++) std::cin >> a[i];
build(1, 1, n);
for (int i = 1; i <= q; i++) {
int typ; std::cin >> typ;
if ( typ == 1 ) {
int x, d; std::cin >> x >> d;
change(1, 1, n, x, d);
}
else {
int l, r; std::cin >> l >> r;
auto ans = query(1, 1, n, l, r);
std::cout << ans.mss << '\n';
}
}
return 0;
}

三:完成建树、查询、单点修改(实际上只有建树递归到点上初始化信息、单点修改递归到点上修改信息的代码有变化)

void build(int id, int l, int r) {
if (l == r) {
seg[id].f = {a[l], a[l], a[l], a[l]};
}
else {
int mid = ( l + r ) >> 1;
build( id * 2, l, mid );
build (id * 2 + 1, mid + 1, r );
update(id);
}
}
Info query(int id, int l, int r, int ql, int qr) {
if ( l == ql && r == qr ) {
return seg[id].f;
}
else {
int mid = ( l + r ) >> 1;
if (qr <= mid) return query( id * 2, l, mid, ql, qr );
else if (ql > mid) return query( id * 2 + 1, mid + 1, r, ql, qr );
else return query( id * 2, l, mid, ql, mid ) + query( id * 2 + 1, mid + 1, r, mid + 1, qr );
}
}
void change(int id, int l, int r, int pos, int d) {
if ( l == r ) {
seg[id].f = {d, d, d, d};
}
else {
int mid = ( l + r ) >> 1;
if ( pos <= mid ) change( id * 2, l, mid, pos, d );
else change( id * 2 + 1, mid + 1, r, pos, d );
update(id);
}
}

完整代码

view
#include <bits/stdc++.h>
const int N = 200005;
int a[N];
struct Info {
long long mss, mpre, msuf, s; // 最大子段和,最大前缀和,最大后缀和,区间和
};
struct Node {
Info f;
} seg[N * 4];
Info operator + (const Info &l, const Info &r) {
Info ret;
ret.mss = std::max({l.mss, r.mss, l.msuf + r.mpre});
ret.mpre = std::max(l.mpre, l.s + r.mpre);
ret.msuf = std::max(r.msuf, l.msuf + r.s);
ret.s = l.s + r.s;
return ret;
}
void update(int id) {
seg[id].f = seg[ id * 2 ].f + seg[ id * 2 + 1 ].f;
}
void build(int id, int l, int r) {
if (l == r) {
seg[id].f = {a[l], a[l], a[l], a[l]};
}
else {
int mid = ( l + r ) >> 1;
build( id * 2, l, mid );
build (id * 2 + 1, mid + 1, r );
update(id);
}
}
Info query(int id, int l, int r, int ql, int qr) {
if ( l == ql && r == qr ) {
return seg[id].f;
}
else {
int mid = ( l + r ) >> 1;
if (qr <= mid) return query( id * 2, l, mid, ql, qr );
else if (ql > mid) return query( id * 2 + 1, mid + 1, r, ql, qr );
else return query( id * 2, l, mid, ql, mid ) + query( id * 2 + 1, mid + 1, r, mid + 1, qr );
}
}
void change(int id, int l, int r, int pos, int d) {
if ( l == r ) {
seg[id].f = {d, d, d, d};
}
else {
int mid = ( l + r ) >> 1;
if ( pos <= mid ) change( id * 2, l, mid, pos, d );
else change( id * 2 + 1, mid + 1, r, pos, d );
update(id);
}
}
int main() {
int n, q;
std::cin >> n >> q;
for (int i = 1; i <= n; i++) std::cin >> a[i];
build(1, 1, n);
for (int i = 1; i <= q; i++) {
int typ; std::cin >> typ;
if ( typ == 1 ) {
int x, d; std::cin >> x >> d;
change(1, 1, n, x, d);
}
else {
int l, r; std::cin >> l >> r;
auto ans = query(1, 1, n, l, r);
std::cout << ans.mss << '\n';
}
}
return 0;
}
posted @   zsxuan  阅读(23)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示