当前位置: 首页 > backend >正文

c++线段树之单点修改区间最大子段和-----P4513 小白逛公园

题目大意

  • 单点修改
  • 查询区间最大字段和
解题思路

如果线段树节点存储的是‘区间最大子段和’,如何合并?
简单的加法或求极值都不行,仔细分析可得,父节点最大字段和可能为:

  • 左子树最大子段和
  • 右子树最大子段和
  • 左子树最大后缀和+右子树最大前缀和

数据结构

线段树存储:
  • 区间总和
  • 区间最大前缀和
  • 区间最大后缀和
  • 区间最大子段和

实现细节

合并操作:在构建和更新线段树时,合并左右子节点的信息,以维护当前节点的四个值。

查询操作:递归查询区间,合并结果时考虑左右子区间的不同情况,确保正确计算最大子段和。

// P4513 小白逛公园, 单点修改,区间查最大子段和
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
#define INF 1000000000
#define MANX 2000002
#define lson (root*2)
#define rson (root*2+1)struct Node {int total; // 区间和int prefix; // 最大前缀和int suffix; // 最大后缀和int max_sum; // 最大字段和
} sgmt[MANX];void push_up(int root) {sgmt[root].total = sgmt[lson].total + sgmt[rson].total;sgmt[root].prefix = max(sgmt[lson].prefix, sgmt[lson].total+sgmt[rson].prefix);sgmt[root].suffix = max(sgmt[rson].suffix, sgmt[rson].total+sgmt[lson].suffix);sgmt[root].max_sum = max({sgmt[lson].max_sum, sgmt[rson].max_sum, sgmt[lson].suffix+sgmt[rson].prefix});
}void update(int a, int b, int l, int r, int root) {if (l == r) {sgmt[root].total = sgmt[root].prefix = sgmt[root].suffix = sgmt[root].max_sum = b;return;}int mid = (l+r)/2;if (a <= mid)  update(a,b,l,mid,lson);else update(a,b,mid+1,r,rson);push_up(root);
}Node query(int a, int b, int l, int r, int root) {if (a <= l && r <= b) return sgmt[root];Node left = {0,-INF,-INF,-INF}, right = {0,-INF,-INF,-INF};int mid = (l+r)/2;if (a <= mid) left = query(a,b,l,mid,lson);if (b > mid) right = query(a,b,mid+1,r,rson);if (left.max_sum == -INF) return right;if (right.max_sum == -INF) return left;Node merged;merged.total = left.total + right.total;merged.prefix = max(left.prefix, left.total+right.prefix);merged.suffix = max(right.suffix, right.total+left.suffix);merged.max_sum = max({left.max_sum, right.max_sum, left.suffix+right.prefix});return merged;
}void build(int l, int r, int root) {if (l == r) return;int mid = (l+r)/2;build(l, mid, lson);build(mid+1, r, rson);push_up(root);
}int main() {ios::sync_with_stdio(0);cin.tie(0); cout.tie(0);int n, m; cin >> n >> m;int npot = 1<<(int)ceil(log2(n));for (int i = 0; i < npot; ++i)if (i < n) {cin >> sgmt[npot+i].total;sgmt[npot+i].prefix = sgmt[npot+i].suffix = sgmt[npot+i].max_sum = sgmt[npot+i].total;} else {sgmt[npot+i].prefix = sgmt[npot+i].suffix = sgmt[npot+i].max_sum = -INF; // 无效值}int left = 1, right = npot, root = 1;build(left, right, root);while (m--) {int op, a, b;cin >> op >> a >> b;if (op == 1) {if (a > b) swap(a, b);Node res = query(a, b, left, right, root);cout << res.max_sum << '\n';} else {update(a, b, left, right, root);}}return 0;
http://www.xdnf.cn/news/7210.html

相关文章:

  • 仿腾讯会议——房间界面用户设置
  • SRIO(Serial RapidIO)握手流程
  • 校园网--tarjan求缩点的两个经典问题
  • 《Python星球日记》 第90天:微调的概念以及如何微调大模型?
  • CCpro工程编程软件
  • 二:操作系统之进程的创建与终止
  • CVE-2018-1273源码分析与漏洞复现
  • 76.有符号数累加运算
  • c++进阶——位图、布隆过滤器
  • 菜鸟之路Day32一一多表查询,事物,索引
  • 【Linux网络】五种IO模型与阻塞IO
  • 多模态信息提取:打通数据价值的“最后一公里”
  • Linux进程信号(二)之信号产生1
  • 【Linux】第二十章 管理基本存储
  • Redis进阶知识
  • 数据库blog2_数据结构与效率
  • 选择之困:如何挑选合适的 Python 环境与工具——以 Google Colaboratory 为例
  • 0-1背包问题(求最优值和构造最优解)
  • 苍穹外卖--修改菜品
  • C++中的四种强制转换
  • web中路径问题
  • Leetcode134加油站
  • u深度学习 神经网络图像数据的预处理全解
  • RDD-数据清洗
  • 02 Nginx虚拟主机
  • 【Linux】第十七章 归档和传输文件
  • 为什么el-select组件在下拉选择后无法赋值
  • 机器学习西瓜书
  • 我的电赛(简易的波形发生器大一暑假回顾)
  • 字节跳动开源通用图像定制模型DreamO,支持风格转换、换衣、身份定制、多条件组合等多种功能~