线段树区间的最大连续子段和-----思维

给定长度为N的数列A,以及M条指令,每条指令可能是以下两种之一:

1、“1 x y”,查询区间 [x,y] 中的最大连续子段和,即 maxx≤l≤r≤y{∑ri=lA[i]}。

2、“2 x y”,把 A[x] 改成 y。

对于每个查询指令,输出一个整数表示答案。

输入格式
第一行两个整数N,M。

第二行N个整数A[i]。

接下来M行每行3个整数k,x,y,k=1表示查询(此时如果x>y,请交换x,y),k=2表示修改。

输出格式
对于每个查询指令输出一个整数表示答案。

每个答案占一行。

数据范围
N≤500000,M≤100000
输入样例:
5 3
1 2 -3 4 5
1 2 3
2 2 -1
1 3 2
输出样例:
2
-1

解析:
我们需要维护4个信息
1.最大前缀和
2.最大后缀和
3.最大连续子段和
4.区间和
4的操作很好维护。
我们来讲3
如果询问区间正好在左区间那么很简单就是左区间的最大子段和
如果询问区间正好在右区间那么很简单就是右区间的最大字段和
如果询问区间在左右子区间,那么就是左区间的最大后缀和+右区间的最大前缀和
三个取max.
讲1和讲2
如果询问区间正好在左区间很简单就是左区间的最大前缀和
如果询问区间正好在右区间很简单就是右区间的最大后缀和。
如果询问区间覆盖了左区间并且也存在右区间中,那么就是左区间的区间和+右区间的最大前缀和
如果询问区间覆盖了右区间并且也存在左区间中,那么就是右区间的区间和+左区间的最大前缀和
四者取max



#include<bits/stdc++.h>
using namespace std;
const int N=5e5+1000;
int n,m,x,y;
int a[N];
struct Node
{
	int l,r; //区间左右端点 
	int sum;//区间和 
	int lmax;//最大前缀和 
	int rmax;//最大后缀和 
	int tmax;//最大连续子段和 
}tr[N<<4]; 
void push_up(Node &u,Node &l,Node &r)
{
	u.sum=l.sum+r.sum;
	u.lmax=max(l.lmax,l.sum+r.lmax);
	u.rmax=max(r.rmax,r.sum+l.rmax);
	u.tmax=max(max(l.tmax,r.tmax),l.rmax+r.lmax);
}
void push_up(int u)
{
	push_up(tr[u],tr[u<<1],tr[u<<1|1]);
 } 
 void build(int u,int l,int r)
 {

 	if(l==r)
 	{
 		tr[u]={l,r,a[r],a[r],a[r],a[r]};
 		return ;
	}
	int mid=l+r>>1;
	tr[u]={l,r};
	build(u<<1,l,mid);
	build(u<<1|1,mid+1,r);
	push_up(u);
	
 }
void  update(int u,int x,int v)
 {
 	if(tr[u].l==tr[u].r)
 	{
 		tr[u]={x,x,v,v,v,v};
 		return ;
	}
	int mid=tr[u].l+tr[u].r>>1;
	if(x<=mid) update(u<<1,x,v);
	else update(u<<1|1,x,v);
	push_up(u);
 }
 Node query(int u,int l,int r)
 {
 	if(l<=tr[u].l&&r>=tr[u].r) return tr[u];
 	int mid=tr[u].l+tr[u].r>>1;
 	if(r<=mid) return query(u<<1,l,r);//在左区间 
 	else if(l>mid) return query(u<<1|1,l,r);//在右区间
	else
	{
		auto left=query(u<<1,l,r);
		auto right=query(u<<1|1,l,r);
		Node res;
		push_up(res,left,right) ;
		return res;
	} 
 }
int main()
{
	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	build(1,1,n);
	int op;
	while(m--)
	{
		scanf("%d %d %d",&op,&x,&y);
		if(op==1)
		{
			if(x>y) swap(x,y) ;
			cout<<query(1,x,y).tmax<<endl;
		}
		else
		{
			update(1,x,y);
		}
	}
}

发布了309 篇原创文章 · 获赞 6 · 访问量 5249

猜你喜欢

转载自blog.csdn.net/qq_43690454/article/details/104085376