2023集 数据结构5 GSS3 - Can you answer these queries III

GSS3 - Can you answer these queries III

题面翻译

n n n 个数, q q q 次操作

操作0 x y A x A_x Ax 修改为 y y y

操作1 l r询问区间 [ l , r ] [l, r] [l,r] 的最大子段和

感谢 @Edgration 提供的翻译

题目描述

You are given a sequence A of N (N <= 50000) integers between -10000 and 10000. On this sequence you have to apply M (M <= 50000) operations:
modify the i-th element in the sequence or for given x y print max{Ai + Ai+1 + … + Aj | x<=i<=j<=y }.

输入格式

The first line of input contains an integer N. The following line contains N integers, representing the sequence A1…AN.
The third line contains an integer M. The next M lines contain the operations in following form:
0 x y: modify Ax into y (|y|<=10000).
1 x y: print max{Ai + Ai+1 + … + Aj | x<=i<=j<=y }.

输出格式

For each query, print an integer as the problem required.

样例 #1

样例输入 #1

4
1 2 3 4
4
1 1 3
0 3 -3
1 2 4
1 3 3

样例输出 #1

6
4
-3

思路

求区间最大字段和,有三种可能:
第一种,在左子树中的最大子段和;
第二种,在右子树中的最大子段和;
第三种,左子树的最大后缀加上右子树的最大前缀;
三种情况取max即可得到答案

完整代码

#include<bits/stdc++.h>
using namespace std;
const int M=1e5+5;
#define int long long
int a[M];
#define lc ((x)<<1)
#define rc ((x)<<1|1)
struct node{
	int maxn,pre,suf,sum;//maxn表示最大子段和,pre表示最大前缀,suf表示最大后缀,sum表示原本数值
};node seg[M<<2];
int n,m;
void pushup(int x)
{
	int l=lc,r=rc;
	seg[x].sum=seg[l].sum+seg[r].sum;
	seg[x].pre=max(seg[l].pre,seg[l].sum+seg[r].pre);
	seg[x].suf=max(seg[r].suf,seg[r].sum+seg[l].suf);
	seg[x].maxn=max(max(seg[l].maxn,seg[r].maxn),seg[l].suf+seg[r].pre);
}//更新
inline void build(int x,int l,int r)
{
	if(l==r)
	{
		seg[x].maxn=seg[x].pre=seg[x].suf=seg[x].sum=a[l];
		return;
	} 
	int mid=(l+r)>>1;
	build(lc,l,mid);build(rc,mid+1,r);
	pushup(x);
}//建树
inline void update(int x,int l,int r,int L,int R)
{
	if(L<l or r<L) return;
	if(l==r&&l==L)
	{
		seg[x].maxn=seg[x].pre=seg[x].suf=seg[x].sum=R;
		return;
	}
	int mid=(l+r)>>1;
	update(lc,l,mid,L,R);
	update(rc,mid+1,r,L,R);
	pushup(x);
}//单点修改
node query(int x,int l,int r,int L,int R)
{
	if(l>=L&&r<=R)return seg[x];
	int mid=(l+r)>>1;bool f1=0,f2=0;
	node left,right;
	if(L<=mid)left=query(lc,l,mid,L,R),f1=1;
	if(R>mid)right=query(rc,mid+1,r,L,R),f2=1;
	node ans;
	if(f1&&f2)
	{
		ans.sum=left.sum+right.sum;
		ans.pre=max(left.pre,left.sum+right.pre);
		ans.suf=max(right.suf,right.sum+left.suf);
		ans.maxn=max(max(left.maxn,right.maxn),left.suf+right.pre);
	}
	else if(f1)ans=left;
	else ans=right;
	return ans;
}//区间查询
void solve()
{
	int x,y,z;
	cin>>z>>x>>y;
	if(z)cout<<query(1,1,n,x,y).maxn<<endl;
	else update(1,1,n,x,y);
}//循环操作
signed main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
		cin>>a[i];
	cin>>m;	//输入
	build(1,1,n);
	while(m--)
	 	solve();
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值