求区间最大子段和(线段树模板)

const int maxn = 50100;
struct node{
    int l,r;
    int maxl,maxr,maxs;	//左子区间,右子区间,总区间最大子段和
    int sum;	//区间总和
}tree[maxn<<2];
int num[maxn];
void update(node &now,node &lt,node &rt)
{
	now.sum = lt.sum + rt.sum;
	now.maxl = max(lt.maxl,lt.sum+rt.maxl);
	now.maxr = max(rt.maxr,rt.sum+lt.maxr);
	now.maxs = max(lt.maxs,rt.maxs);
	now.maxs = max(now.maxs,lt.maxr+rt.maxl);
	return ;
}
void build(int k,int l,int r)
{
	tree[k].l = l,tree[k].r = r;
	if(l == r){
		tree[k].maxs = num[l];
		tree[k].maxl = num[l];
		tree[k].maxr = num[l];
		tree[k].sum = num[l];
		return ;
	}
	int mid = (l+r)>>1;
	build(k<<1,l,mid);
	build(k<<1|1,mid+1,r);

	update(tree[k],tree[k*2],tree[k*2+1]);
	return ;
}

void change(int k,int x,int y)
{
	if(tree[k].l == x && tree[k].r == x){
		tree[k].maxs = y;
		tree[k].sum = y;
		tree[k].maxl = y;
		tree[k].maxr = y;
		return ;
	}

	int mid = (tree[k].l + tree[k].r)>>1;

	if(x<=mid)
		change(k<<1,x,y);
	else
		change(k<<1|1,x,y);

	update(tree[k],tree[k<<1],tree[k<<1|1]);
	return ;
}

node query(int k,int l,int r)
{
	if(tree[k].l>=l&&tree[k].r<=r){
		return tree[k];
	}

	int mid = (tree[k].l+tree[k].r)>>1;

	if(r <= mid)	//这里注意,当查询区在左子区间时,直接查询左子区间
		return query(k<<1,l,r);
	else if(l > mid)	//这里注意,当查询区在右子区间时,直接查询右子区间
		return query(k<<1|1,l,r);
	else{	//左右都有就………
		node left,right,result;

		left = query(k<<1,l,mid);
		right = query(k<<1|1,mid+1,r);

		update(result,left,right);
		return result;
	}
}

模板题:Can you answer these queries III

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 }.

Input
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 }.
Output
For each query, print an integer as the problem required.

Example
Input:
4
1 2 3 4
4
1 1 3
0 3 -3
1 2 4
1 3 3

Output:
6
4
-3

注意结果超出 int 范围
AC代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<ctype.h>
#include<vector>
#include<algorithm>
#include<sstream>
#define PI acos(-1.0)
using namespace std;
typedef long long ll;
const int maxn = 50100;
struct node{
    ll l,r;
    ll maxl,maxr,maxs;
    ll sum;
}tree[maxn<<2];
ll num[maxn];
void update(node &now,node &lt,node &rt)
{
	now.sum = lt.sum + rt.sum;
	now.maxl = max(lt.maxl,lt.sum+rt.maxl);
	now.maxr = max(rt.maxr,rt.sum+lt.maxr);
	now.maxs = max(lt.maxs,rt.maxs);
	now.maxs = max(now.maxs,lt.maxr+rt.maxl);
	return ;
}
void build(int k,ll l,ll r)
{
	tree[k].l = l,tree[k].r = r;
	if(l == r){
		tree[k].maxs = num[l];
		tree[k].maxl = num[l];
		tree[k].maxr = num[l];
		tree[k].sum = num[l];
		return ;
	}
	ll mid = (l+r)>>1;
	build(k<<1,l,mid);
	build(k<<1|1,mid+1,r);

	update(tree[k],tree[k*2],tree[k*2+1]);
	return ;
}

void change(int k,ll x,ll y)
{
	if(tree[k].l == x && tree[k].r == x){
		tree[k].maxs = y;
		tree[k].sum = y;
		tree[k].maxl = y;
		tree[k].maxr = y;
		return ;
	}

	ll mid = (tree[k].l + tree[k].r)>>1;

	if(x<=mid)
		change(k<<1,x,y);
	else
		change(k<<1|1,x,y);

	update(tree[k],tree[k<<1],tree[k<<1|1]);
	return ;
}

node query(ll k,ll l,ll r)
{
	if(tree[k].l>=l&&tree[k].r<=r){
		return tree[k];
	}

	ll mid = (tree[k].l+tree[k].r)>>1;

	if(r <= mid)
		return query(k<<1,l,r);
	else if(l > mid)
		return query(k<<1|1,l,r);
	else{
		node left,right,result;

		left = query(k<<1,l,mid);
		right = query(k<<1|1,mid+1,r);

		update(result,left,right);
		return result;
	}
}
int main(void)
{
    int n,m;
    int a;
    ll b,c;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%lld",num+i);
    build(1,1,n);
    scanf("%d",&m);
    while(m--){
        scanf("%d%lld%lld",&a,&b,&c);
        if(a==0)    change(1,b,c);
        if(a==1){
            printf("%lld\n",query(1,b,c).maxs);
        }
    }
    return 0;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逃夭丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值