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<bits/stdc++.h>
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;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值