Can you answer these queries III--线段树求最大连续子段和

题目链接:https://cn.vjudge.net/problem/SPOJ-GSS3

题目大意:n个数,m次操作,0,x,y,表示把a[x]位置的数改为y,1,x,y,表示求[x,y]的最大连续子段和。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 50010;
int n, m;
ll a[N];
struct node{
	int l, r;
	ll ls, rs, ms,sum;
}tr[N<<2];
void pushup(int m)
{
	tr[m].sum = tr[m<<1].sum + tr[m<<1|1].sum;
	tr[m].ls = max(tr[m<<1].ls, tr[m<<1].sum + tr[m<<1|1].ls);
	tr[m].rs = max(tr[m<<1|1].rs, tr[m<<1|1].sum + tr[m<<1].rs);
	tr[m].ms = max(tr[m<<1].rs + tr[m<<1|1].ls, max(tr[m<<1].ms, tr[m<<1|1].ms));
}
void build(int m, int l, int r)
{
	tr[m].l = l;
	tr[m].r = r;
	if(l == r)
	{
		tr[m].ls = tr[m].rs = tr[m].ms = tr[m].sum = a[l];
		return ;
	}
	int mid = (l + r) >> 1;
	build(m<<1, l, mid);
	build(m<<1|1, mid + 1, r);
	pushup(m);
}
void updata(int m, int id, ll val)
{
	if(tr[m].l == id && tr[m].r == id)
	{
		tr[m].ls = tr[m].rs = tr[m].ms = tr[m].sum = val;
		return ;
	}
	int mid = (tr[m].l + tr[m].r) >> 1;
	if(id <= mid)
		updata(m<<1, id, val);
	else
		updata(m<<1|1, id, val);
	pushup(m);
}
node ask(int m, int l, int r)
{
	if(tr[m].l == l && tr[m].r == r)
		return tr[m];
	int mid = (tr[m].l + tr[m].r) >> 1;
	if(r <= mid)
		return ask(m<<1, l, r);
	else if(l > mid)
		return ask(m<<1|1, l, r);
	else
	{
		node a, b, c;
		a = ask(m<<1, l, mid);
		b = ask(m<<1|1, mid + 1, r);
		c.sum = a.sum + b.sum;
		c.ls = max(a.ls, a.sum + b.ls);
		c.rs = max(b.rs, b.sum + a.rs);
		c.ms = max(a.rs + b.ls, max(a.ms, b.ms));
		return c;
	}
}
int main()
{
	while(~scanf("%d", &n))
	{
		for(int i = 1; i <= n; i++)
			scanf("%lld", &a[i]);
		build(1, 1, n);
		scanf("%d", &m);
		int op;
		while(m--)
		{
			scanf("%d", &op);
			if(op == 0)
			{
				int x;
				ll val;
				scanf("%d %lld", &x, &val);
				updata(1, x, val);
			}
			else
			{
				int l, r;
				scanf("%d %d", &l, &r);
				if(l > r)
					swap(l, r);
				node tmp = ask(1, l, r);
				printf("%lld\n", tmp.ms);
			}
		}
	}
	return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值