数组版线段树,调试了半天还是没找出来,求指正

P4513 小白逛公园

Virtualtan @ 2019-07-25 10:02:23

#include<cstdio>
#include<algorithm>
using namespace std;
#define MAX 500000+99

int n,m, a[MAX];
int sumv[MAX<<2], lm[MAX<<2], rm[MAX<<2], xm[MAX<<2];
/*
画图分析,几种情况
[a,b]中最大子段和 =
max( [左子树的最大子段和, 右子树的最大子段和, 过中间点且不到a,b的最大字段和 )
即: xm[o] = max( xm[o<<1], xm[o<<1|1],  rm[o<<1]+lm[o<<1|1])
//注意这里是左子树和右子树的最大子段和, 而不是lm[o] 和 rm[o], 因为它最大的时候可能不经过边界
lm[o] = max(lm[o<<1], sumv[o<<1]+lm[o<<1|1] )
rm[o] = max(rm[o<<1|1], sumv[o<<1|1]+rm[o<<1] )
*/
void push_up(int o) {
    sumv[o] = sumv[o<<1] + sumv[o<<1|1];
    lm[o] = max(lm[o<<1], sumv[o<<1]+lm[o<<1|1]);
    rm[o] = max(rm[o<<1|1], sumv[o<<1|1]+rm[o<<1]);
    xm[o] = max( max(xm[o<<1], xm[o<<1|1]), rm[o<<1]+lm[o<<1|1] );//.......
}

void build(int o, int l, int r) {
    if(l == r) {
        sumv[o] = lm[o] = rm[o] = xm[o] = a[l];
        return  ;
    }
    int mid = (l+r)>>1;
    build(o<<1, l, mid);
    build(o<<1|1, mid+1, r);
    push_up(o);
}

void update(int o, int l, int r, int t, int v) {
    if(l == r) {
        sumv[o] = lm[o] = rm[o] = xm[o] = v;
        return ;
    }
    int mid = (l+r)>>1;
    if(t <= mid) update(o<<1, l, mid, t, v);
    else update(o<<1|1, mid+1, r, t, v);
    push_up(o);
}

int query(int o, int l, int r, int ql, int qr) {
    if(ql <= l && r <= qr) return xm[o];
    int mid = (l+r)>>1;
    int ans2 = 2147000047;
    int ans1 = 2147000047;
    if(ql <= mid) ans1 = query(o<<1, l, mid, ql, qr);
    if(mid < qr) ans2 = query(o<<1|1, mid+1, r, ql, qr);
    if(ans1 == 2147000047) return ans2;
    if(ans2 == 2147000047) return ans1;
    return max(ans1, ans2);
}

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

|