acwing245. 你能回答这些问题吗(线段树维护组大连续子段和)

题意

在这里插入图片描述

思路

  1. 单点修改比较好维护,但是区间连续子段和就比较难维护了,我们需要在结构提供维护一些间接条件,在这些间接条件的帮助下我们才能维护出最大连续字段和,我们需要在结构体中维护的条件如下 :
    1. 当前区间最大连续子段和:mx
    2. 当前区间的和:sum
    3. 当前区间的前缀最大值: lmx
    4. 当前区间的后缀最大值:rmx
  2. 维护关系如下图。

在这里插入图片描述
3. 注意区间最大连续子段和 mx 的产生有三种情况:

  1. 最大子段和只在左子区间中产生:l.mx
  2. 最大子段和只在有子区间中产生:r.mx
  3. 最大子段和横跨两个子区间 l,r:l.rmx + r.lmx

代码

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

#define ls (k << 1)
#define rs (k << 1 | 1)

const int N = 500005;
int n, m, a[N];
struct Tree
{
    
    
    int l, r;
    int sum, lmx, rmx, mx;
} tr[N * 4];

void push_up(Tree & u, Tree l, Tree r)
{
    
    
    u.sum = l.sum + r.sum;
    u.lmx = max(l.lmx, l.sum + r.lmx);
    u.rmx = max(r.rmx, r.sum + l.rmx);
    u.mx = max(max(l.mx, r.mx), l.rmx + r.lmx);
}

void build(int k, int l, int r)
{
    
    
    tr[k] = {
    
     l, r };
    if (l == r)
    {
    
    
        tr[k] = {
    
     l, r, a[l], a[l], a[l], a[l] };
        return;
    }

    int md = (l + r) >> 1;
    build(ls, l, md);
    build(rs, md + 1, r);
    push_up(tr[k], tr[ls], tr[rs]);
}

void update(int k, int x, int v)
{
    
    
    if (tr[k].l == x && tr[k].r == x) 
    {
    
    
        tr[k] = {
    
     x, x, v, v, v, v };
        return;
    }

    int md = (tr[k].l + tr[k].r) >> 1;
    if (x <= md) update(ls, x, v);
    else update(rs, x, v);
    push_up(tr[k], tr[ls], tr[rs]);
}

Tree query(int k, int l, int r)
{
    
    
    if (tr[k].l >= l && tr[k].r <= r) return tr[k];

    int md = (tr[k].l + tr[k].r) >> 1;

    if (r <= md) return query(ls, l, r);
    else if (l > md) return query(rs, l, r);
    else
    {
    
    
        Tree t;
        push_up(t, query(ls, l, r), query(rs, l, r));
        return t;
    }
}

int main()
{
    
    
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; i ++) scanf("%d", &a[i]);
    build(1, 1, n);
    int op, x, y;
    while (m --)
    {
    
    
        scanf("%d %d %d", &op, &x, &y);
        if (op == 1)
        {
    
    
            if (x > y) swap(x, y);
            printf("%d\n", query(1, x, y).mx);
        }
        else
        {
    
    
            update(1, x, y);
        }
    }


    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_34261446/article/details/121139049
245