• GSS3 Can you answer these queries III


    与GSS1对比,只是增加了一个单点修改。

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 1e6 + 10;
    typedef long long LL;
    int n, m, a[N];
    //宏定义左右儿子
    #define ls u << 1
    #define rs (u << 1) | 1
    
    //三个数字取最大值
    int max(int a, int b, int c) {
        return max(a, max(b, c));
    }
    
    struct Node {
        int l, r;
        int pre; //前缀最大值
        int suf; //后缀最大值
        int max; //区间内连续最大和
        int sum; //区间和
    } tr[N << 2];
    
    void pushup(int u) {
        // 区间最大值= max(左半边,右半边,左后+右前)
        tr[u].max = max(tr[ls].max, tr[rs].max, tr[ls].suf + tr[rs].pre);
        // 区间前缀最大值=max(左前缀最大值,左总和+右前缀最大值)
        tr[u].pre = max(tr[ls].pre, tr[ls].sum + tr[rs].pre);
        // 区间后缀最大值=max(左后缀最大值+右总和,右后缀最大值)
        tr[u].suf = max(tr[ls].suf + tr[rs].sum, tr[rs].suf);
        // 区间和=左区间和+右区间和
        tr[u].sum = tr[ls].sum + tr[rs].sum;
    }
    
    void build(int u, int l, int r) {
        tr[u] = {l, r};
        if (l == r) {
            tr[u].sum = tr[u].pre = tr[u].suf = tr[u].max = a[l]; //初始化
            return;
        }
        int mid = (l + r) >> 1;
        build(ls, l, mid), build(rs, mid + 1, r);
        //向父节点推送
        pushup(u);
    }
    
    Node query(int u, int l, int r) {
        if (l <= tr[u].l && r >= tr[u].r) return tr[u]; //完全命中
        int mid = (tr[u].l + tr[u].r) >> 1;             //中点
        if (l > mid) return query(rs, l, r);            //只在右半边
        if (r <= mid) return query(ls, l, r);           //只在左半边
        Node a, b, c;                                   //在左右两边
        a = query(ls, l, r), b = query(rs, l, r);       //分别查询左右儿子区间
        c.sum = a.sum + b.sum;                          //区间和=左儿子区间和+右儿子区间和
        c.max = max(a.max, b.max, a.suf + b.pre);       //区间序列最大值=max(左儿子最大,右儿子最大,左后+右前)
        c.pre = max(a.pre, a.sum + b.pre);              //区间前缀最大值=max(左前缀最大值,左区间和+右前缀最大值)
        c.suf = max(b.suf, b.sum + a.suf);              //区间后缀最大值=max(右后缀最大值,右区间和+左区间后缀最大值)
        return c;                                       //终于拼接好了,可以返回了
    }
    void modify(int u, int x, int v) {
        if (tr[u].l == tr[u].r) {
            tr[u].max = tr[u].pre = tr[u].suf = tr[u].sum = v;
            return;
        }
        int mid = (tr[u].l + tr[u].r) >> 1;
        if (x <= mid)
            modify(ls, x, v);
        else
            modify(rs, x, v);
        pushup(u);
    }
    int main() {
        cin >> n;
        for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
        //构建线段树
        build(1, 1, n);
    
        cin >> m;
        int x, y;
        while (m--) {
            int op;
            scanf("%d%d%d", &op, &x, &y);
            if (op == 0)
                modify(1, x, y);
            else
                printf("%d\n", query(1, x, y).max);
        }
        return 0;
    }
    
  • 相关阅读:
    ECMAScript 引用类型Object 对象
    jQuery Form Plugin
    在 PHP5 中使用 DOM 控制 XML
    JavaScript encodeURI()和encodeURIComponent() 函数
    程序员进阶的建议:多看、多写、多交流
    jQuery 取 css zindex 值在各种浏览器中的返回值
    XPath 语法教程(Tutorial_2)
    使用 strpos 需要注意 === 运算符
    关于代码开发规范和原则
    PHP 编写大型网站问题集
  • 原文地址:https://www.cnblogs.com/littlehb/p/16204777.html
Copyright © 2020-2023  润新知