线段树维护区间最大子段和

 一段区间的最大子段和出现在以下三种情况:左区间/右区间/跨越中间

void push(node &now,node <,node &rt)
{	
	now.sum = lt.sum + rt.sum;
	now.lgss = max(lt.lgss,lt.sum+rt.lgss);
	now.rgss = max(rt.rgss,rt.sum+lt.rgss);
	now.gss = max(lt.gss,max(rt.gss,lt.rgss+rt.lgss));
	return ; 
}

 查询时在最后可能会出现需求区间跨越两个子区间,所以需要再暴力合并一下

    if(r <= mid)
		return query(now*2,l,r);
	else if(l >= mid+1 )
		return query(now*2+1,l,r);
	else
	{
		node left,right,result;
		
		left = query(2*now,l,mid);
		right = query(2*now+1,mid+1,r);
		
		push(result,left,right);
		return result;
	}

单点修改就是暴力二分递归到叶子节点修改 

void update(ll now,ll dis,ll val)  //单点修改 
{
	if(tree[now].l == dis && tree[now].r == dis)
	{
		tree[now].gss = val;
		tree[now].sum = val;
		tree[now].lgss = val;
		tree[now].rgss = val;
		return ;
	}
	
	ll mid = (tree[now].l + tree[now].r)/2;
	
	if(dis <= mid)
		update(now*2,dis,val);
	else
		update(now*2+1,dis,val);
	
	push(tree[now],tree[now*2],tree[now*2+1]);
	return ;
}

 


模板题:https://www.acwing.com/problem/content/description/246/  (模板代码非此题AC代码,需改动一下)

【模板】

#include 
#define endl '\n'
using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
//typedef __int128 bll;
const ll maxn = 5e5+100;
const ll mod = 1e9+7;
const ld pi = acos(-1.0);
const ll inf = 1e18;
const ld eps = 1e-5;
const ld e = exp(1);

ll n,arr[maxn],m;
struct node
{
	ll l,r;
	ll sum,lgss,rgss,gss;
}tree[maxn<<2];

void push(node &now,node <,node &rt)
{	
	now.sum = lt.sum + rt.sum;
	now.lgss = max(lt.lgss,lt.sum+rt.lgss);
	now.rgss = max(rt.rgss,rt.sum+lt.rgss);
	now.gss = max(lt.gss,max(rt.gss,lt.rgss+rt.lgss));
	return ; 
}

void build(ll now,ll l,ll r)
{
	tree[now].l = l,tree[now].r = r;
	
	if(l == r)
	{
		tree[now].gss = arr[l];
		tree[now].lgss = arr[l];
		tree[now].rgss = arr[l];
		tree[now].sum = arr[l];
		return ;
	}
	
	ll mid = (l+r)/2;
	build(now*2,l,mid);
	build(now*2+1,mid+1,r);
	
	push(tree[now],tree[now*2],tree[now*2+1]);
	return ;
}

void update(ll now,ll dis,ll val)  //单点修改 
{
	if(tree[now].l == dis && tree[now].r == dis)
	{
		tree[now].gss = val;
		tree[now].sum = val;
		tree[now].lgss = val;
		tree[now].rgss = val;
		return ;
	}
	
	ll mid = (tree[now].l + tree[now].r)/2;
	
	if(dis <= mid)
		update(now*2,dis,val);
	else
		update(now*2+1,dis,val);
	
	push(tree[now],tree[now*2],tree[now*2+1]);
	return ;
}

node query(ll now,ll l,ll r)
{
	if(tree[now].l >= l && tree[now].r <= r)
	{
		return tree[now];
	}
	
	ll mid = (tree[now].l+tree[now].r)/2;
	
	if(r <= mid)
		return query(now*2,l,r);
	else if(l >= mid+1 )
		return query(now*2+1,l,r);
	else
	{
		node left,right,result;
		
		left = query(2*now,l,mid);
		right = query(2*now+1,mid+1,r);
		
		push(result,left,right);
		return result;
	}
		
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	
	cin >> n >> m;
	for(ll i = 1; i <= n; i++)
	{
		cin >> arr[i];
	}
	
	build(1,1,n);
	
	while(m--)
	{
		ll t,x,y;
		cin >> t >> x >> y;
		if(t == 1)
		{
			cout << query(1,x,y).gss << endl;
		}
		else
		{
			update(1,x,y);
		}
	}
	
	return 0;
}

 

你可能感兴趣的:(线段树)