zoukankan      html  css  js  c++  java
  • SPOJ GSS1_Can you answer these queries I(线段树区间合并)

    SPOJ GSS1_Can you answer these queries I(线段树区间合并)

    标签(空格分隔): 线段树区间合并


    题目链接
    GSS1 - Can you answer these queries I

    You are given a sequence A1, A[2], ..., A[N] . ( |A[i]| ≤ 15007 , 1 ≤ N ≤ 50000 ). A query is defined as follows:
    Query(x,y) = Max { a[i]+a[i+1]+...+a[j] ; x ≤ i ≤ j ≤ y }.
    Given M queries, your program must output the results of these queries.

    Input

    The first line of the input file contains the integer N.
    In the second line, N numbers follow.
    The third line contains the integer M.
    M lines follow, where line i contains 2 numbers xi and yi.
    Output

    Your program should output the results of the M queries, one query per line.
    Example

    Input:
    3
    -1 2 3
    1
    1 2
    Output:
    2

    题意:

    求连续自区间最大和
    

    题解:

    线段树的区间合并可以解决有关连续子区间最值的问题,介绍一下,每一个节点都保存一个此区间的子区间最大值,那么在区间合并的时候就会遇到如何处理包含断点子区间的问题,我们用一个lv保存从左端点开始的连续子区间最值,用rv保存从到右端点结束的连续子区间最值,v表示整个区间的所有元素和,ans表示这个区间的连续子区间的最值。
    那么有合并的时候v要考虑从左孩子的右端点结束加上右孩子的左端点开始,和左孩子和右孩子的ans最大值
    lv要考虑的是左孩子的左端点开始或者是整个左孩子的所有值加上右孩子的从左端点开始的值
    同样rv要考虑的是右孩子的右端点结束或者是整个右孩子的所有值加上左孩子的右端点结束的值
    参考代码如下
    
    void Push(int d){
        st[d].v = st[lc].v+st[rc].v;
        st[d].lv = max(st[lc].lv,st[lc].v+st[rc].lv);
        st[d].rv = max(st[rc].rv,st[rc].v+st[lc].rv);
        st[d].ans = max(max(st[lc].ans,st[rc].ans),st[lc].rv+st[rc].lv);
        return;
    }
    

    代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N = 50008;
    #define mid (l+r>>1)
    #define lc d<<1
    #define rc d<<1|1
    
    struct Tr{
        int v,lv,rv,ans;
    }st[N<<2];
    void Push(int d){
        st[d].v = st[lc].v+st[rc].v;
        st[d].lv = max(st[lc].lv,st[lc].v+st[rc].lv);
        st[d].rv = max(st[rc].rv,st[rc].v+st[lc].rv);
        st[d].ans = max(max(st[lc].ans,st[rc].ans),st[lc].rv+st[rc].lv);
        return;
    }
    void build(int l, int r, int d){
        if(l==r){
            scanf("%d",&st[d].ans);
            st[d].v = st[d].lv = st[d].rv = st[d].ans;
            return;
        }
        build(l,mid,lc);
        build(mid+1,r,rc);
        Push(d);
    }
    Tr query(int L, int R, int l, int r, int d)
    {
        if(l==L&&R==r){
            return st[d];
        }
        else if(R<=mid) return query(L,R,l,mid,lc);
        else if(L>mid) return query(L,R,mid+1,r,rc);
        Tr la = query(L,mid,l,mid,lc);
        Tr ra = query(mid+1,R,mid+1,r,rc);
        Tr re;
        re.v = la.v+ra.v;
        re.lv = max(la.lv,la.v+ra.lv);
        re.rv = max(ra.rv,ra.v+la.rv);
        re.ans = max(max(ra.ans,la.ans),la.rv+ra.lv);
        return re;
    }
    int main()
    {
        int n,m;
        int ll,rr;
        while(~scanf("%d",&n))
        {
            build(1,n,1);
            scanf("%d",&m);
            while(m--)
            {
                scanf("%d%d",&ll,&rr);
                Tr fn = query(ll,rr,1,n,1);
                printf("%d
    ",fn.ans);
            }
        }
        return 0;
    }
    
    
  • 相关阅读:
    ubuntu更强大的包管理工具:aptitude
    ubuntu下载自带的java-1.8
    [机器学习] ML重要概念:梯度(Gradient)与梯度下降法(Gradient Descent)
    不能下载程序
    为什么你的电脑会变得越来越慢?
    win7常用键
    C# 遍历枚举(枚举是目的,遍历(获取)是手段)
    基于PCIe的高速接口设计
    Xilinx中的xapp1052理解
    把Xilinx的IPCORE解密成源代码的方法
  • 原文地址:https://www.cnblogs.com/shanyr/p/5710152.html
Copyright © 2011-2022 走看看