SPOJ GSS3 (区间最大子段和 + 单点更新) (线段树)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ShadowGhostH/article/details/81673360

题目

思路

详细思路移步GSS1这里只是加入了一个单点更新得操作,找到要更新得顶点,然后把它更改,再递归调用回溯的时候维护区间特征值
E n d

代码

struct Node{
    int l, r;
    int sum, maxs, maxl, maxr;  //区间和, 区间最大子段和, 最大前缀和, 最大后缀和
}tree[maxn<<2];
int num[maxn];               //数值数组

void build(int i, int l, int r){
    tree[i].l = l;
    tree[i].r = r;
    if(l == r){
        tree[i].sum  = num[l];
        tree[i].maxs = num[l];
        tree[i].maxl = num[l];
        tree[i].maxr = num[l];
        return ;
    }

    int mid = (l+r)>>1;
    build(i<<1, l, mid);
    build(i<<1|1, mid+1, r);    //子树建树后更新特征值

    tree[i].sum  = tree[i<<1].sum + tree[i<<1|1].sum;
    tree[i].maxs = max(max(tree[i<<1].maxs, tree[i<<1|1].maxs), tree[i<<1].maxr+tree[i<<1|1].maxl);
    tree[i].maxl = max(tree[i<<1].maxl, tree[i<<1].sum+tree[i<<1|1].maxl);
    tree[i].maxr = max(tree[i<<1|1].maxr, tree[i<<1|1].sum+tree[i<<1].maxr);

    return ;
}

Node query(int i, int l, int r){
    if(tree[i].l==l && tree[i].r==r)
        return tree[i];

    int mid = (tree[i].l+tree[i].r)>>1;
    if(mid >= r)
        return query(i<<1, l, r);
    else if(mid < l)
        return query(i<<1|1, l, r);
    else {
        Node ls = query(i, l, mid);
        Node rs = query(i, mid+1, r);

        ls.maxs = max(max(ls.maxs, rs.maxs), ls.maxr+rs.maxl);
        ls.maxl = max(ls.maxl, ls.sum+rs.maxl);
        ls.maxr = max(rs.maxr, rs.sum+ls.maxr);
        ls.sum  = ls.sum + rs.sum;

        return ls;
    }
}

void update(int i, int x, int k){
    if(tree[i].l == tree[i].r){
        tree[i].sum  = k;
        tree[i].maxs = k;
        tree[i].maxl = k;
        tree[i].maxr = k;
        return ;
    }

    int mid = (tree[i].l+tree[i].r)>>1;
    if(x<=mid) update(i<<1, x, k);
    else update(i<<1|1, x, k);

    tree[i].sum  = tree[i<<1].sum + tree[i<<1|1].sum;
    tree[i].maxs = max(max(tree[i<<1].maxs, tree[i<<1|1].maxs), tree[i<<1].maxr+tree[i<<1|1].maxl);
    tree[i].maxl = max(tree[i<<1].maxl, tree[i<<1].sum+tree[i<<1|1].maxl);
    tree[i].maxr = max(tree[i<<1|1].maxr, tree[i<<1|1].sum+tree[i<<1].maxr);
}

int main()
{
    int n, m;
    sd(n);
    rep(i, 1, n+1)
        sd(num[i]);

    build(1, 1, n);
    sd(m);
    rep(i, 0, m) {
        int op, l, r;
        sddd(op, l, r);
        if(op == 0) update(1, l, r);
        else if(op == 1) {
            Node ans = query(1, l, r);
            printf("%d\n", ans.maxs);
        }
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/ShadowGhostH/article/details/81673360