zoukankan      html  css  js  c++  java
  • SP1716 GSS3 Can you answer these queries III (线段树维护最大连续子段和)

    题目大意:

        给定数列A以及M条指令      "1 x y" 查询[x, y]中的最大连续子段和 "2 x y"把A[x] 改成y

    单点修改的操作不再赘述 对于维护最大连续子段和的思路如下:

    先从二叉树的视角考虑一下线段树中所有的情况:

    tmax为最大连续子段和 最大前缀和为lmax 最大后缀和为rmax

    1. 只需要递归左子区间或只需要递归右子区间

    tmax = max (tmax, left_son)

     tmax = max(tmax, right_son)

     2.区间横跨mid(不与端点重合)时, 则需要同时递归左右子区间

    此时还需维护左子区间的最大后缀和以及右子区间的最大前缀和

    此时横跨左右子区间的最大子段和 = 左子区间的最大后缀和 + 右子区间的最大前缀和

    tmax = max(tmax, left_son.rmax + right_son.lmax)

    3.计算前缀/后缀

     tmax = max(tmax, left_son.sum + right_son.lmax)

    4.完全覆盖该区间

      直接返回即可

     由此可知 线段树结构体中需要维护端点信息l和r,  最大前缀和lmax 最大后缀和rmax 当前区间和sum

    线段树思想中有一点很关键, 就是要找到所有需要维护的信息应对各个情况, 需要让结构体中的信息具有完备性

    查询时为了简化操作 用pushup更新并返回结构体

    完整代码如下:

    /*
     * @Author: Hellcat
     * @Date: 2020-03-10 14:15:14
     */
    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 5e4 + 10;
    
    int n, m, a[N];
    struct node {
        int l, r;
        int tmax; // 最大连续子段和
        int lmax; // 最大前缀和
        int rmax; // 最大后缀和
        int sum;  // 区间[l, r]中的最大值
    }tr[N<<2];
    
    void pushup(node &u, node &l, node &r) {
        u.sum = l.sum + r.sum;
        u.lmax = max(l.lmax, l.sum + r.lmax);
        u.rmax = max(r.rmax, r.sum + l.rmax);
        u.tmax = max(max(l.tmax, r.tmax), l.rmax + r.lmax);
    }
    
    void pushup(int u) {
        pushup(tr[u], tr[u<<1], tr[u<<1 | 1]);
    }
    
    void build(int u, int l, int r) {
        tr[u] = {l, r, a[r], a[r], a[r], a[r]};
        if(l == r) return;
        int mid = (l + r) >> 1;
        build(u<<1, l, mid);
        build(u<<1 | 1, mid + 1, r);
        pushup(u);
    }
    
    void modify(int u, int x, int v) {
        if(tr[u].l == tr[u].r) { tr[u] = {x, x, v, v, v, v}; return; }
        int mid = (tr[u].l + tr[u].r) >> 1;
        if(x <= mid) modify(u << 1, x, v);
        else modify(u << 1 | 1, x, v);
        pushup(u);
    }
    
    node query(int u, int l, int r) {
        if(l <= tr[u].l && tr[u].r <= r) return tr[u];
        int mid = (tr[u].l + tr[u].r) >> 1;
        if(r <= mid) return query(u << 1, l, r);
        if(l > mid) return query(u << 1 | 1, l, r);
        auto left = query(u << 1, l, r);
        auto right = query(u << 1 | 1, l, r);
        node res;
        pushup(res, left, right);
        return res;
    }
    
    int main() {
        scanf("%d", &n);
        for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
        build(1, 1, n);
        int p; scanf("%d", &p);
        while(p--) {
            int op, x, y;
            scanf("%d%d%d", &op, &x, &y);
            if(op == 0) modify(1, x, y);
            else {
                node res = query(1, x, y);
                printf("%d\n", res.tmax);
            }
        }
    }
  • 相关阅读:
    conda更换为清华镜像源
    NVDIA的GPU驱动升级
    Windows使用nvidia-smi查看GPU信息
    查询GPU是否支持CUDA
    PyTorch教程【一】Pytorch环境的配置及安装
    JAVA基础篇—继承
    SQL
    随机数
    hdu 4751 Divide Groups 二分图
    hdu 4126 Genghis Khan the Conqueror hdu 4756 Install Air Conditioning 最小生成树
  • 原文地址:https://www.cnblogs.com/tedukuri/p/12456363.html
Copyright © 2011-2022 走看看