蓝书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
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 pii;
typedef std::vector 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 << '\n';
}
return 0;
}