(模板)线段树求区间最大子段和 SP1043 GSS1 - Can you answer these queries I

题意:给出一个区间,m次询问,每次询问区间最大子段和。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 5e4 + 10;
int n, M, w, l, r;
struct node {
    int sum;//[l,r]区间之和
    int msum;//[l,r]内的最大子段和
    int mpre;//[l,r]内的最大前缀和t
    int mpost;//[l,r]内的最大后缀和
} t[N << 2];
void pushup(int rt) {
    int ls = rt << 1, rs = rt << 1 | 1;
    //区间之和 = 左区间之和+右区间之和
    t[rt].sum = t[ls].sum + t[rs].sum;
    //区间最大子段和 = max(左区间最大子段和,右区间最大子段和,左区间最大后缀和+右区间最大前缀和)
    t[rt].msum = max(max(t[ls].msum, t[rs].msum), t[ls].mpost + t[rs].mpre);
    //区间最大前缀和 = max(左区间最大前缀和,左区间之和+右区间最大前缀和)
    t[rt].mpre = max(t[ls].mpre, t[rs].mpre + t[ls].sum);
    //区间最大后缀和 = max(右区间最大后缀和,右区间之和+左区间最大后缀和)
    t[rt].mpost = max(t[rs].mpost, t[ls].mpost + t[rs].sum);
}
void build(int l, int r, int rt) {
    if(l == r) {
        scanf("%d", &w);
        t[rt].sum = t[rt].msum = t[rt].mpre = t[rt].mpost = w;
        return;
    }
    int m = (l + r) >> 1;
    build(l, m, rt << 1);
    build(m + 1, r, rt << 1 | 1);
    pushup(rt);
}
node query(int L, int R, int l, int r, int rt) {
    if(L <= l && r <= R)
        return t[rt];
    int m = (l + r) >> 1;
    if(R <= m)
        return query(L, R, l, m, rt << 1);
    else if(m < L)
        return query(L, R, m + 1, r, rt << 1 | 1);
    else {
        node ans, ls = query(L, R, l, m, rt << 1), rs = query(L, R, m + 1, r, rt << 1 | 1);
        ans.sum = ls.sum + rs.sum;
        ans.msum = max(max(ls.msum, rs.msum), ls.mpost + rs.mpre);
        ans.mpost = max(rs.mpost, ls.mpost + rs.sum);
        ans.mpre = max(ls.mpre, rs.mpre + ls.sum);
        return ans;
    }

}
int main() {
    scanf("%d", &n);
    build(1, n, 1);
    scanf("%d", &M);
    while(M--) {
        scanf("%d%d", &l, &r);
        printf("%d\n", query(l, r, 1, n, 1).msum);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值