首页 > 代码库 > asdasd

asdasd

 

 

 

/*
    线段树区间操作GSS 
    一段长的区间的 GSS 有三种情况:
    1 完全在左子区间
    2 完全在右子区间
    3 横跨左右区间
    前两种情况可使用子区间的 GSS,但如何处理第三种情况?
    注意到可以把区间拆成两部分,这两部分是不相关的。
    所以需要维护一个区间的“最大左子段和”和“最大右子段和”。
    gss = MAX{l.gss,r.gss,l.rgss + r.lgss}
    由 GSS 一直推下来,对于每个节点,一共需要设计4个状态。 
    1 GSS:最大子段和
    2 LGSS:最大左子段和
    3 RGSS:最大右子段和
    4 SUM:整段和
*/
#include <cstdio>

#define Max 202090

inline long long max (long long a, long long b)
{
    return a > b ? a : b;
}

void read (long long &now)
{
    now = 0;
    register char word = getchar ();
    bool flag = false;
    while (word < 0 || word > 9)
    {
        if (word == -)
            flag = true;
        word = getchar ();
    }
    while (word >= 0 && word <= 9)
    {
        now = now * 10 + word - 0;
        word = getchar ();
    }
    if (flag)
        now = -now;
}

struct Segment_Tree_Type
{
    struct Segment_Tree
    {
        long long l;
        long long r;
        long long Mid;
        long long Sum;
        long long Max_Suffix;
        long long Max_Prefix;
        long long Max_Sum;
    };
    
    Segment_Tree tree[Max << 3];
    
    void Build (long long l, long long r, long long now)
    {
        tree[now].l = l;
        tree[now].r = r;
        if (l == r)
        {
            read (tree[now].Sum);
            tree[now].Max_Sum = tree[now].Sum;
            tree[now].Max_Suffix = tree[now].Sum;
            tree[now].Max_Prefix = tree[now].Sum;
            return ;
        }
        tree[now].Mid = (l + r) >> 1;
        Build (l, tree[now].Mid, now << 1);
        Build (tree[now].Mid + 1, r, now << 1 | 1);
        tree[now].Max_Prefix = max (tree[now << 1].Max_Prefix, tree[now << 1].Sum + tree[now << 1 | 1].Max_Prefix);
        tree[now].Max_Suffix = max (tree[now << 1 | 1].Max_Suffix, tree[now << 1 | 1].Sum + tree[now << 1].Max_Suffix);
        tree[now].Max_Sum = max (tree[now << 1].Max_Suffix + tree[now << 1 | 1].Max_Prefix, max (tree[now << 1].Max_Sum, tree[now << 1 | 1].Max_Sum));
        tree[now].Sum = tree[now << 1].Sum + tree[now << 1 | 1].Sum;
    }
    
    
    Segment_Tree Query_section (long long l, long long r, long long now)
    {
        Segment_Tree Suffix, Prefix;
        Segment_Tree res;
        if (tree[now].l == l && tree[now].r == r)
            return tree[now];
        if (r <= tree[now].Mid)
            return Query_section (l, r, now << 1);
        else if (l > tree[now].Mid)
            return Query_section (l, r, now << 1 | 1);
        else
        {
            Prefix = Query_section (l, tree[now].Mid, now << 1);
            Suffix = Query_section (tree[now].Mid + 1, r, now << 1 | 1);
            res.Max_Prefix = max (Prefix.Max_Prefix, Prefix.Sum + Suffix.Max_Prefix);
            res.Max_Suffix = max (Suffix.Max_Suffix, Suffix.Sum + Prefix.Max_Suffix);
            res.Max_Sum = max (Prefix.Max_Suffix + Suffix.Max_Prefix, max (Prefix.Max_Sum, Suffix.Max_Sum));
        } 
        return res;
    }
    
};

Segment_Tree_Type Tree;

long long N;

int main (int argc, char *argv[])
{
    read (N);
    Tree.Build (1, N, 1); 
    read (N);
    long long x, y;
    while (N--)
    {
        read (x);
        read (y);
        printf ("%lld\n", Tree.Query_section (x, y, 1).Max_Sum); 
    }
    return 0;
}

 

asdasd