• GSS1


    原题链接

    • 题意:线段树经典问题,多组询问,问区间内,最大连续字段和。
    • 题解:难的地方在于询问时候的处理,就是返回的是一个结构体,然后里面有 (Lmax) 即前缀最大连续子段和, (Rmax) 后缀最大连续子段和还有 (datamax) 即最大连续子段和,还有 (sum) 即区间内的和,然后如何询问,就是如果要询问的区间在当前 (p_mid) 的完全的右边,就返回右边,然后如果当前区间在 (p_mid) 的左边,返回左边,否则就都问一下然后合并。
    • 代码:
    #include <iostream>
    
    using namespace std;
    
    const int N = 1e5 + 9;
    typedef long long ll;
    ll a[N];
    struct Segment_tree{ 
        struct node {
            ll l, r, L, R, Lmax, Rmax, datamax, sum;
        }tr[N << 2];
        inline void pushup(ll p){
            int L = tr[p].l;
            int R = tr[p].r;
            tr[p].datamax = max(max(tr[L].datamax, tr[R].datamax), tr[L].Rmax + tr[R].Lmax);
            tr[p].sum = tr[L].sum + tr[R].sum;
            tr[p].Lmax = max(tr[L].Lmax, tr[L].sum + tr[R].Lmax);
            tr[p].Rmax = max(tr[R].Rmax, tr[R].sum + tr[L].Rmax);
            tr[p].datamax = max(max(tr[L].datamax, tr[R].datamax), tr[L].Rmax + tr[R].Lmax);
            tr[p].datamax = max(tr[p].datamax, max(tr[p].Lmax, tr[p].Rmax));
        } 
        inline void build(ll l, ll r, ll p) {
            tr[p].L = l, tr[p].R = r, tr[p].l = p << 1, tr[p].r = p <<  1 | 1;
            if (l == r) {
                tr[p].datamax = a[l];
                tr[p].Lmax = a[l];
                tr[p].Rmax = a[r];
                tr[p].sum = a[l];
                return ;
            }
            int mid = l + r >> 1;
            build(l, mid, tr[p].l);
            build(mid + 1, r, tr[p].r);
            pushup(p);
        }
        inline node ask(ll l, ll r, ll p) {
            if (tr[p].L>=l && tr[p].R <= r) 
            {
                return tr[p];
            }
            int mid = tr[p].L + tr[p].R >> 1;
            if (l >= mid + 1)return ask(l, r, tr[p].r);
            if (r <= mid)return ask(l, r, tr[p].l);
            node a = ask(l, r, tr[p].l);
            node b = ask(l, r, tr[p].r);
            node ret;
            ret.Lmax = max(a.Lmax, a.sum + b.Lmax);
            ret.Rmax = max(b.Rmax, b.sum + a.Rmax);
            ret.datamax = max(a.datamax, b.datamax);
            ret.datamax = max(ret.datamax, a.Rmax + b.Lmax);
            ret.datamax = max(ret.datamax, max(ret.Lmax, ret.Rmax));
            ret.sum = a.sum + b.sum;
            return ret;
        }
    }T;
    int main() {
        int n;scanf("%d",&n);
        for (int i =1; i <=n; i ++ ) scanf("%lld", &a[i]);
        T.build(1, n, 1);
        int m;
        scanf("%d", &m);
        while (m--) {
            ll l, r;
            scanf("%lld%lld", &l, &r);
            if (l > r)swap(l, r);
            printf("%lld
    ", T.ask(l, r, 1).datamax);
        }
    }
    
  • 相关阅读:
    Extjs Ext.ux.IFrame的用法 以及父子窗口间函数相互调用
    Android ADB server didn't ACK * failed to start daemon * 简单有效的解决方案
    Java sun.misc.Unsafe类的学习笔记
    Java 并发编程学习笔记 理解CLH队列锁算法
    深入理解Java虚拟机 -- 读书笔记(1):JVM运行时数据区域
    Java并发编程学习笔记 深入理解volatile关键字的作用
    JVM Client Server启动设置
    双重检查锁定与延迟初始化
    Tomcat 添加为系统服务 开机自动启动
    配置TOMCAT 修改默认ROOT路径
  • 原文地址:https://www.cnblogs.com/Xiao-yan/p/14703870.html
Copyright © 2020-2023  润新知