题目链接:点这里
题目描述
在小新家附近有一条“公园路”,路的一边从南到北依次排着 n 个公园,小白早就看花了眼,自己也不清楚该去哪些公园玩了。
一开始,小白就根据公园的风景给每个公园打了分。小新为了省事,每次遛狗的时候都会事先规定一个范围,小白只可以选择第 a 个和第 b 个公园之间(包括 a,b 两个公园)选择连续的一些公园玩。小白当然希望选出的公园的分数总和尽量高咯。同时,由于一些公园的景观会有所改变,所以,小白的打分也可能会有一些变化。
那么,就请你来帮小白选择公园吧。
输入格式
第一行,两个整数 n 和 m,分别表示表示公园的数量和操作(遛狗或者改变打分)总数。
接下来 n 行,每行一个整数,依次给出小白开始时对公园的打分。
接下来 m 行,每行三个整数。其中第一个整数 k 为 1 或 2。
k=1 表示,小新要带小白出去玩,接下来的两个整数 a 和 b 给出了选择公园的范围 (1≤a,b≤n)。测试数据可能会出现 a>b 的情况,需要进行交换;
k=2 表示,小白改变了对某个公园的打分,接下来的两个整数 p 和 s,表示小白对第 p 个公园的打分变成了 s(1≤p≤N)。
输出格式
小白每出去玩一次,都对应输出一行,只包含一个整数,表示小白可以选出的公园得分和的最大值。
一句话题意:
维护一个数组a,满足以下两个操作
一、更改位于p位置的数值为s
二、求出给出的区间[l,r]中a的最大子段和
一句话思路
直接上线段树没什么好说的了吧
思路
除了node和mergenode()其他都和普通的线段树板子一样
接下来说怎么写node和mergenode()
node:存四个变量:
1: sum:本段总长度
2: lmax:包括区间最左端的点时最大值
3: rmax:包括区间最右端的点时最大值
4: maxx:本段最大子段和
mergenode(node a,node b)
其中需要维护node中的四个变量
1: sum:没什么好说的直接a.sum+b.sum就完了
2: lmax:取a.lmax和a.sum+b.lmax中最大的那个
3: rmax:取b.rmax和a.rmax+b.sum中最大的那个
4: maxx:取a.maxx,b.maxx和a.rmax+b.lmax中最大的那个
显而易见这个是对的
代码:
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int x = 0, f = 1;char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-') f = -1;ch = getchar();}
while(ch >= '0' && ch <= '9'){x = (x << 3) + (x << 1) + ch - '0';ch = getchar();}
return x * f;
}
int n, m;
const int maxn = 5e5 + 10, maxm = 1e5 + 10;
class Segment_tree{
private:
struct node{
int lmax,rmax,maxx,sum;
}d[maxn * 4];
node mergenode(node a,node b){
node tmp;
tmp.lmax = max(a.lmax,a.sum + b.lmax);
tmp.rmax = max(b.rmax,b.sum + a.rmax);
tmp.maxx = max(max(a.maxx,b.maxx),a.rmax + b.lmax);
tmp.sum = a.sum + b.sum;
return tmp;
}
void build(int l,int r,int p){
if(l == r){d[p].lmax = d[p].rmax = d[p].maxx = d[p].sum = a[l];return;}
int mid = (l + r) >> 1;build(l,mid,p << 1);build(mid + 1,r,(p << 1) | 1);
d[p] = mergenode(d[p << 1],d[(p << 1) | 1]);
}
void update(int x,int s,int t,int p,int change){
if(s == t && s == x){d[p] = {change,change,change, change};return;}
int mid = (s + t) >> 1;
if(mid >= x)update(x,s,mid,p << 1,change);
else update(x,mid + 1,t,(p << 1) | 1,change);
d[p] = mergenode(d[p << 1],d[(p << 1) | 1]);
}
node query(int l,int r,int s,int t,int p){
if(l <= s && t <= r)return d[p];
int mid = (s + t) >> 1;
if(mid >= r)return query(l,r,s,mid,p << 1);
else if(mid < l)return query(l,r,mid + 1,t,(p << 1) | 1);
else return mergenode(query(l,r,s,mid,p << 1),query(l,r,mid + 1,t,(p << 1) | 1));
}
public:
int a[maxn];
void build(int n){build(1,n,1);}
void update(int pos,int change){update(pos,1,n,1,change);}
int query(int x,int y){if(x > y)swap(x,y);return query(x,y,1,n,1).maxx;}
}tree;
signed main(){
n = read(); m = read();
for(int i = 1;i <= n;i++){tree.a[i] = read();}
tree.build(n); int op, x, y;
for(int i = 1;i <= m;i++){
op = read(); x = read(); y = read();
if(op == 1)printf("%d\n",tree.query(x,y));
else tree.update(x,y);
}
return 0;
}