洛谷P4513 小白逛公园

本文详细介绍了一种数据结构——线段树,并提供了具体的实现代码。通过实例演示了线段树的基本操作,如构建、查询及单点更新等,特别关注区间最大值、左最大值和右最大值的维护。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

线段树日常操作。

维护left,right,sum,large表示左右最大,总和,区间最大。

然后瞎搞搞就OK了。

pushup l == r 的时候 left right large 都等于 sum

查询的时候分类讨论力度要大...

由于只有单点修改所以没有标记,比较爽。

洛谷的数据,记得把输入的两个数比较,可能要swap

 

  1 #include <cstdio>
  2 #include <algorithm>
  3 
  4 const int N = 500010, INF = 0x3f3f3f3f;
  5 
  6 struct SegmentTree {
  7     int large[N << 2], left[N << 2], right[N << 2], sum[N << 2];
  8 
  9     inline void pushup(int l, int r, int o) {
 10         if(l == r) {
 11             large[o] = sum[o];
 12             //left[o] = right[o] = std::max(sum[o], 0);
 13             left[o] = right[o] = sum[o];
 14             return;
 15         }
 16         int ls = o << 1;
 17         int rs = ls | 1;
 18         sum[o] = sum[ls] + sum[rs];
 19         large[o] = std::max(large[ls], large[rs]);
 20         large[o] = std::max(large[o], left[rs] + right[ls]);
 21         left[o] = std::max(left[ls], sum[ls] + left[rs]);
 22         right[o] = std::max(right[rs], sum[rs] + right[ls]);
 23         return;
 24     }
 25 
 26     void change(int p, int l, int r, int o, int v) {
 27         if(l == r) {
 28             sum[o] = v;
 29             pushup(l, r, o);
 30             return;
 31         }
 32         int mid = (l + r) >> 1;
 33         if(p <= mid) {
 34             change(p, l, mid, o << 1, v);
 35         }
 36         else {
 37             change(p, mid + 1, r, o << 1 | 1, v);
 38         }
 39         pushup(l, r, o);
 40         return;
 41     }
 42     int getsum(int L, int R, int l, int r, int o) {
 43         if(L <= l && r <= R) {
 44             return sum[o];
 45         }
 46         if(r < L || R < l) {
 47             return 0;
 48         }
 49         int mid = (l + r) >> 1;
 50         return getsum(L, R, l, mid, o << 1) + getsum(L, R, mid + 1, r, o << 1 | 1);
 51     }
 52     void ask(int L, int R, int l, int r, int o, int &ans, int &la, int &ra) {
 53         if(L <= l && r <= R) {
 54             ans = large[o];
 55             la = left[o];
 56             ra = right[o];
 57             return;
 58         }
 59         int mid = (l + r) >> 1;
 60         if(R <= mid) {
 61             ask(L, R, l, mid, o << 1, ans, la, ra);
 62             return;
 63         }
 64         if(mid < L) {
 65             ask(L, R, mid + 1, r, o << 1 | 1, ans, la, ra);
 66             return;
 67         }
 68         int A = -INF;
 69         int B = A, C = A, D = A, E = A, F = A;
 70         ask(L, R, l, mid, o << 1, A, B, C);
 71         ask(L, R, mid + 1, r, o << 1 | 1, D, E, F);
 72         ans = std::max(A, D);
 73         ans = std::max(ans, C + E);
 74         if(L <= l) {
 75             la = std::max(B, sum[o << 1] + E);
 76         }
 77         else {
 78             la = std::max(B, E + getsum(L, mid, l, mid, o << 1));
 79         }
 80         if(R >= mid) {
 81             ra = std::max(F, sum[o << 1 | 1] + C);
 82         }
 83         else {
 84             ra = std::max(F, C + getsum(mid + 1, R, mid + 1, r, o << 1 | 1));
 85         }
 86         return;
 87     }
 88     void build(int l, int r, int o) {
 89         if(l == r) {
 90             scanf("%d", &sum[o]);
 91             pushup(l, r, o);
 92             return;
 93         }
 94         int mid = (l + r) >> 1;
 95         build(l, mid, o << 1);
 96         build(mid + 1, r, o << 1 | 1);
 97         pushup(l, r, o);
 98         return;
 99     }
100 }SgT;
101 
102 int main() {
103     int n, m;
104     scanf("%d%d", &n, &m);
105     SgT.build(1, n, 1);
106     int f, x, y;
107     while(m--) {
108         scanf("%d%d%d", &f, &x, &y);
109         if(f == 1) {
110             if(x > y) {
111                 std::swap(x, y);
112             }
113             int A, B, C;
114             SgT.ask(x, y, 1, n, 1, A, B, C);
115             printf("%d\n", A);
116         }
117         else {
118             SgT.change(x, 1, n, 1, y);
119         }
120     }
121     return 0;
122 }
AC代码

 

转载于:https://www.cnblogs.com/huyufeifei/p/9354525.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值