HUST1722(线段树维护区间最大连续和)

1722 - East Ninth Road

Time Limit: 2s Memory Limit: 256MB
Submissions: 195 Solved: 11
DESCRIPTION
Pyy now is in the third year of college and he has a lot of spare time to have fun. So he joined the school photography community
There is a line of trees by the HUST East Ninth Road (hai). Every day when pyy pass a section of the road he will choose the most beautiful line of trees to take pictures.
But because of the weather, every tree is not the same in every day. So pyy scores each tree, and he will dynamically modify the score.
INPUT
There are multiple sets of data
For each set of data:
The first line, two integers N and M represent the total number of trees and the total number of operations (taking pictures or modifying the score)respectively.
The next N lines, each row an integer, is the score of the tree given by pyy at the beginning.
The next M lines, three integers per line. The first integer K is 1 or 2.
K = 1 means that pyy passes through a section of the road and is ready to take pictures. The next two integers a and b give the range of the selected park (1≤a, b≤N), a may be greater than b.
K = 2 means that pyy modified the score of a tree, the next two integers p and s, says that the score of the p-th tree is changed to s(1 ≤ p ≤ N).

Among them, 1 ≤ N ≤ 500000, 1 ≤ M ≤ 100000, all scoring is an absolute value of not more than 1000 integer.
OUTPUT
Each time Pyy pass a section of the road will correspond to one line output, contains only one integer, said the max sum of the score of the trees selected by pyy.
Note: As pyy want to practice his skill, so every time he pass the road will at least take photo of one tree, even if the tree is not beautiful.
SAMPLE INPUT
5 3
1 2 -3 4 5
1 2 3
2 2 -1
1 2 3
SAMPLE OUTPUT
2
-1
HINT
SOURCE
pengyanyu

解题思路:每次询问让你求出区间最大连续和,我们用线段树维护4个东西就行,一个区间和,一个区间最大连续和,一个从区间左边界开始的最大连续和,一个从区间右边界开始的最大连续和,区间合并时用这几个变量搞一下就行。

#include
using namespace std;
const int maxn = 5e5 + 10;
int N, M;
int father[maxn];
struct node{
    int l, r;
    int sum;//区间和
    int Max;//最大区间和
    int lmax;//区间从左边开始最大连续和
    int rmax;//区间从右边开始最大连续和
}Node[4 * maxn];
void update(int i)
{
    if(i == 1) return;
    int f = i>>1;
    int s1 = f<<1;
    int s2 = s1|1;
    Node[f].sum = Node[s1].sum + Node[s2].sum;//更新区间和
    Node[f].lmax = max(Node[s1].lmax, Node[s1].sum + Node[s2].lmax);
    Node[f].rmax = max(Node[s2].rmax, Node[s2].sum + Node[s1].rmax);//更新区间最大左右和
    Node[f].Max = max(Node[s1].Max, Node[s2].Max);
    Node[f].Max = max(Node[f].Max, Node[s1].rmax + Node[s2].lmax);//更新区间最大连续和
    update(f);

}
void build(int i, int l, int r)
{
    Node[i].l = l;
    Node[i].r = r;
    if(l == r)
    {
        scanf("%d", &Node[i].sum);
        father[l] = i;
        Node[i].Max = Node[i].sum;
        Node[i].lmax = Node[i].sum;
        Node[i].rmax = Node[i].sum;
        update(i);
        return;
    }
    i <<= 1;
    int mid = (l + r)>>1;
    build(i, l, mid);
    build(i|1, mid + 1, r);
}
int querys(int i, int l, int r)
{
    if(Node[i].l == l && Node[i].r == r)
    {
        return Node[i].sum;
    }
    i <<= 1;
    if(r <= Node[i].r) return querys(i, l, r);
    else if(l >= Node[i|1].l) return querys(i|1, l, r);
    else
    {
        return querys(i, l, Node[i].r) + querys(i|1, Node[i|1].l, r);
    }
}
int queryl(int i,int l, int r)
{
    if(Node[i].l == l && Node[i].r == r)
    {
         return Node[i].lmax;
    }
    i <<= 1;
    if(r <= Node[i].r) return queryl(i, l, r);
    else if(l >= Node[i|1].l) return queryl(i|1, l, r);
    else
    {
        int l1 = queryl(i, l, Node[i].r);
        int l2 = queryl(i|1, Node[i|1].l, r);
        int sum = querys(i, l, Node[i].r);
        return max(l1, sum + l2);
    }
}
int queryr(int i,int l, int r)
{
    if(Node[i].l == l && Node[i].r == r)
    {
         return Node[i].rmax;
    }
    i <<= 1;
    if(r <= Node[i].r) return queryr(i, l, r);
    else if(l >= Node[i|1].l) return queryr(i|1, l, r);
    else
    {
        int r1 = queryr(i, l, Node[i].r);
        int r2 = queryr(i|1, Node[i|1].l, r);
        int sum = querys(i|1, Node[i|1].l, r);
        return max(r2, sum + r1);
    }
}
int query(int i, int l, int r)
{
    if(Node[i].l == l && Node[i].r == r)
    {
        return Node[i].Max;
    }
    i <<= 1;
    if(r <= Node[i].r) return query(i, l, r);
    else if(l >= Node[i|1].l) return query(i|1, l, r);
    else
    {
        int ls2 = queryl(i|1, Node[i|1].l, r);
        int rs1 = queryr(i, l, Node[i].r);
        int Maxl = query(i, l, Node[i].r);
        int Maxr = query(i|1, Node[i|1].l, r);
        int Max = max(Maxl, Maxr);
        return max(Max, ls2 + rs1);
    }
}
int main()
{
    while(~scanf("%d%d", &N, &M))
    {
        build(1, 1, N);
        int op, l, r;
        for(int i = 1; i <= M; i++)
        {
            scanf("%d%d%d", &op, &l, &r);
            if(op == 1)
            {
                if(l > r) swap(l, r);
                printf("%d\n", query(1, l, r));
            }
            else
            {
                int ans = father[l];
                Node[ans].sum = r;
                Node[ans].Max = r;
                Node[ans].lmax = r;
                Node[ans].rmax = r;
                update(ans);
            }
        }
    }
    return 0;
}

你可能感兴趣的:(线段树)