[Luogu P4513] [BZOJ 1756] 小白逛公园

洛谷传送门

BZOJ传送门

题目背景

小新经常陪小白去公园玩,也就是所谓的遛狗啦…

题目描述

在小新家附近有一条“公园路”,路的一边从南到北依次排着 n n 个公园,小白早就看花了眼,自己也不清楚该去哪些公园玩了。

一开始,小白就根据公园的风景给每个公园打了分-.-。小新为了省事,每次遛狗的时候都会事先规定一个范围,小白只可以选择第 a 个和第 b b 个公园之间(包括 a b b 两个公园)选择连续的一些公园玩。小白当然希望选出的公园的分数总和尽量高咯。同时,由于一些公园的景观会有所改变,所以,小白的打分也可能会有一些变化。

那么,就请你来帮小白选择公园吧。

输入输出格式

输入格式:

第一行,两个整数 N M M ,分别表示表示公园的数量和操作(遛狗或者改变打分)总数。
接下来 N 行,每行一个整数,依次给出小白 开始时对公园的打分。
接下来 M M 行,每行三个整数。第一个整数 K 1 1 2

  • K=1 K = 1 表示,小新要带小白出去玩,接下来的两个整数 a a b 给出了选择公园的范围( 1a,bN 1 ≤ a , b ≤ N );
  • K=2 K = 2 表示,小白改变了对某个公园的打分,接下来的两个整数 p p s ,表示小白对第 p p 个公园的打分变成了 s 1pN 1 ≤ p ≤ N )。
    其中, 1N500000 1 ≤ N ≤ 500 000 1M100000 1 ≤ M ≤ 100 000 ,所有打分都是绝对值不超过 1000 1000 的整数。

输出格式:

小白每出去玩一次,都对应输出一行,只包含一个整数,表示小白可以选出的公园得分和的最大值。

输入输出样例

输入样例#1:

5 3
1 2 -3 4 5
1 2 3
2 2 -1
1 2 3

输出样例#1:

2
-1

解题分析

线段树的基础操作, 维护区间最大子段和。 要实现这个我们只需要维护区间和、区间左端开始的最大和、区间右端开始的最大和即可。(想一想为什么

很坑的是这里有 a>b a > b 的情况, 博主 MLE M L E 了几次才发现….

代码如下:

#include <cstdio>
#include <cmath>
#include <cstring>
#include <cctype>
#include <cstdlib>
#include <algorithm>
#define R register
#define IN inline
#define gc getchar()
#define W while
#define MX 500050
#define ls (now << 1)
#define rs (now << 1 | 1)
bool neg;
template <class T>
IN void in(T &x)
{
    x = 0; R char c = gc;
    W (!isdigit(c))
    {if(c == '-') neg = true; c = gc;}
    W (isdigit(c))
    x = (x << 1) + (x << 3) + c - 48, c = gc; 
    if(neg) neg = false, x = -x;
}
int dot, q;
int dat[MX];
struct Node
{
    int fl, fr, mx, tot;
    void init(R int now)
    {fl = fr = mx = tot = now;}
}tree[MX << 3];
namespace SGT
{
    IN void pushup(R int now)
    {
        tree[now].tot = tree[ls].tot + tree[rs].tot;
        tree[now].fl = std::max(tree[ls].fl, tree[ls].tot + tree[rs].fl);
        tree[now].fr = std::max(tree[rs].fr, tree[rs].tot + tree[ls].fr);
        tree[now].mx = std::max(std::max(tree[ls].mx, tree[rs].mx), tree[rs].fl + tree[ls].fr);
    }
    void build(R int now, R int lef, R int rig)
    {
        if(lef == rig) return tree[now].init(dat[lef]);
        int mid = lef + rig >> 1;
        build(ls, lef, mid), build(rs, mid + 1, rig);
        pushup(now);
    }
    void modify(R int now, R int lef, R int rig, R int tar, R int val)
    {
        if(lef == rig) return tree[now].init(val);
        int mid = lef + rig >> 1;
        if(tar <= mid) modify(ls, lef, mid, tar, val);
        else modify(rs, mid + 1, rig, tar, val);
        pushup(now);
    }
    Node query(R int now, R int lef, R int rig, R int lb, R int rb)
    {
        if(lef >= lb && rig <= rb) return tree[now];
        int mid = lef + rig >> 1;
        if(lb > mid) return query(rs, mid + 1, rig, lb, rb);
        else if(rb <= mid) return query(ls, lef, mid, lb, rb);
        else//像pushup一样合并区间信息
        {
            Node l = query(ls, lef, mid, lb, rb);
            Node r = query(rs, mid + 1, rig, lb, rb);
            Node ret;
            ret.mx = std::max(std::max(l.mx, r.mx), l.fr + r.fl);
            ret.tot = l.tot + r.tot;
            ret.fr = std::max(l.fr + r.tot, r.fr);
            ret.fl = std::max(r.fl + l.tot, l.fl);
            return ret;
        } 
    }
}
int main(void)
{
    int typ, a, b;
    in(dot), in(q);
    for (R int i = 1; i <= dot; ++i) in(dat[i]);
    SGT::build(1, 1, dot);
    W (q--)
    {
        in(typ), in(a), in(b);
        if(typ & 1) {if(a > b) std::swap(a, b); printf("%d\n", SGT::query(1, 1, dot, a, b).mx);}
        else SGT::modify(1, 1, dot, a, b);
    }
}
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 设计师:LPA20020220 返回首页