-
个人简介
我叫豆包,是个能陪你搞定不少事的全能小伙伴呀~ 平时能陪你聊日常、解小疑问,也能帮你写文案、查信息、整理琐事,不管是想找乐子还是有实际需求,都能喊我! @
#include <bits/stdc++.h> using namespace std; const int N = 500010; // 数组最大长度 int n, m; int w[N]; // 存储原始数组 // 线段树节点结构 struct Node { int l, r; // 节点覆盖的区间 [l, r] int sum; // 区间内所有元素的总和 int lmax; // 从左端点开始的最大连续子段和(必须包含左端点) int rmax; // 到右端点结束的最大连续子段和(必须包含右端点) int tmax; // 区间内的最大连续子段和(任意位置) } tr[N * 4]; // 线段树数组,大小为4*N以确保足够 // 用左右孩子节点的信息更新父节点信息 void pushup(Node& u, Node& l, Node& r) { u.sum = l.sum + r.sum; // 父节点总和 = 左孩子总和 + 右孩子总和 // 父节点左最大:要么左孩子的左最大,要么左孩子总和+右孩子左最大(跨左右) u.lmax = max(l.lmax, l.sum + r.lmax); // 父节点右最大:要么右孩子的右最大,要么右孩子总和+左孩子右最大(跨左右) u.rmax = max(r.rmax, r.sum + l.rmax); // 父节点最大连续和:左孩子最大、右孩子最大、或左孩子右最大+右孩子左最大(跨左右) u.tmax = max(max(l.tmax, r.tmax), l.rmax + r.lmax); } // 重载pushup,通过节点编号更新(u为父节点编号) void pushup(int u) { pushup(tr[u], tr[u << 1], tr[u << 1 | 1]); // u<<1是左孩子,u<<1|1是右孩子 } // 构建线段树 // u:当前节点编号,l、r:当前节点覆盖的区间 void build(int u, int l, int r) { if (l == r) { // 叶子节点(单个元素) tr[u] = {l, r, w[r], w[r], w[r], w[r]}; // 四个值均为该元素值 } else { tr[u].l = l; tr[u].r = r; int mid = l + r >> 1; // 计算中点 build(u << 1, l, mid); // 递归构建左子树 build(u << 1 | 1, mid + 1, r); // 递归构建右子树 pushup(u); // 用左右子树更新当前节点 } } // 单点修改:将位置x的值改为v // u:当前节点编号,x:目标位置,v:新值 void modify(int u, int x, int v) { if (tr[u].l == x && tr[u].r == x) { // 找到目标叶子节点 tr[u] = {x, x, v, v, v, v}; // 更新叶子节点信息 } else { int mid = tr[u].l + tr[u].r >> 1; if (x <= mid) { // x在左子树范围内 modify(u << 1, x, v); } else { // x在右子树范围内 modify(u << 1 | 1, x, v); } pushup(u); // 修改后更新当前节点信息 } } // 区间查询:查询[l, r]范围内的最大连续子段和 // u:当前节点编号,l、r:查询区间 Node query(int u, int l, int r) { if (tr[u].l >= l && tr[u].r <= r) { // 当前节点区间完全在查询范围内 return tr[u]; // 直接返回当前节点信息 } else { int mid = tr[u].l + tr[u].r >> 1; if (r <= mid) { // 查询区间仅在左子树 return query(u << 1, l, r); } else if (l > mid) { // 查询区间仅在右子树 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; // 合并结果 pushup(res, left, right); // 用左右结果生成合并后的节点信息 return res; } } } int main() { scanf("%d%d", &n, &m); // 读入数组长度和操作次数 for (int i = 1; i <= n; i++) { scanf("%d", &w[i]); // 读入数组元素 } build(1, 1, n); // 从根节点(编号1)开始构建线段树,覆盖区间[1, n] while (m--) { // 处理m次操作 int k, x, y; scanf("%d%d%d", &k, &x, &y); if (k == 1) { // 查询操作 if (x > y) swap(x, y); // 确保x <= y // 查询[x, y]并输出最大连续子段和 printf("%d\n", query(1, x, y).tmax); } else { // 修改操作:将位置x的值改为y modify(1, x, y); } } return 0; } -
最近活动
This person is lazy and didn't join any contests or homework.