[SGT] 线段树维护区间最大子段和

蓝书P208

https://vjudge.net/problem/SPOJ-GSS1


若将一区间分为两部分,则必有最大子段存在于左区间 / 右区间 / 跨越中间

因此当前节点记录该段的最大前缀和,最大后缀和,段和,区间内最大子段和

	now.sum = ls.sum + rs.sum;
	now.lmax = max(ls.lmax, ls.sum + rs.lmax);
	now.rmax = max(rs.rmax, rs.sum + ls.rmax);
	now.val = max(ls.val, max( rs.val, ls.rmax + rs.lmax) );

修改,建树时直接按定义push

查询相当于建颗查询区间内的子树再暴力合并至根节点返回

代码

/*
    Zeolim - An AC a day keeps the bug away
*/
 
//pragma GCC optimize(2)
#include <bits/stdc++.h>
using namespace std;

#define mp(x, y) make_pair(x, y)
#define fr(x, z, y) for(int x = z; x < y; ++x)

typedef long long ll;
typedef double ld;
typedef std::pair<int, int> pii;
typedef std::vector <short> vi;
//typedef __int128 ill;

const ld PI = acos(-1.0);
const ld E = exp(1.0);
const ll INF = 1e18;
const ll MOD = 1e9 + 7;
const int MAXN = 1e6 + 100;

int n, m;

struct node
{
	int l, r;
	int val;
	int sum, lmax, rmax;
}tr[MAXN * 4];

int arr[MAXN] = {0};

void push(node &now, node &ls, node &rs)
{
	now.sum = ls.sum + rs.sum;
	now.lmax = max(ls.lmax, ls.sum + rs.lmax);
	now.rmax = max(rs.rmax, rs.sum + ls.rmax);
	now.val = max(ls.val, max( rs.val, ls.rmax + rs.lmax) );
}

void build(int now, int l, int r)
{
	tr[now].l = l, tr[now].r = r;
	int mid = (l + r) / 2;
	if(l == r) {tr[now].val = tr[now].sum = tr[now].lmax = tr[now].rmax = arr[l]; return;}
	build(now * 2, l, mid);
	build(now * 2 + 1, mid + 1, r);
	push(tr[now], tr[now * 2], tr[now * 2 + 1]);
}

void change(int now, int p, int v)
{
	if(tr[now].l == tr[now].r) { tr[now].val = tr[now].sum = tr[now].lmax = tr[now].rmax = v; return;}
	int mid = (tr[now].l + tr[now].r) / 2;
	if(p <= mid) change(now * 2, p, v);
	if(p > mid) change(now * 2 + 1, p, v);
	push(tr[now], tr[now * 2], tr[now * 2 + 1]);
}

node ask(int now, int l, int r)
{
	if(l <= tr[now].l && r >= tr[now].r) return tr[now];
	int mid = (tr[now].l + tr[now].r) / 2;
	if(r <= mid) return ask(now * 2, l, r);
	if(l > mid) return ask(now * 2 + 1, l, r);
	node ls = ask(now * 2, l, r), rs = ask(now * 2 + 1, l, r), ans;
	push(ans, ls, rs);
	return ans;
}


int main()
{  
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    //freopen("d:out.txt","w",stdout);
  	//freopen("d:in.txt","r",stdin);
  	cin >> n;
  	fr(i, 1, n + 1)
  		cin >> arr[i];
  	build(1, 1, n);
  	cin >> m;
  	int op, x, y;
  	fr(i, 0, m)
  	{
  		cin  >> x >> y;
  		cout << ask(1, x, y).val << '
';
  	}
    return 0;
}
原文地址:https://www.cnblogs.com/zeolim/p/12270352.html