While @pkacprzak's answer describes the solution well, some people might prefer a code example.
#include <iostream>
#define ll long long
using namespace std;
const int N=1<<17; // big power of 2 that fits your data
int n,k;
struct P {ll l, r, ts, bs;}; // left, right, totalsum, bestsum
P p[2*N];
ll maxf(ll a,ll b,ll c) {return max(a,max(b,c));}
P combine(P &cl,P &cr) {
P node;
node.ts = cl.ts + cr.ts;
node.l = maxf(cl.l, cl.ts, cl.ts + cr.l);
node.r = maxf(cr.r, cr.ts, cr.ts + cl.r);
node.bs = maxf(cl.bs, cr.bs, cl.r + cr.l);
return node;
}
void change(int k, ll x) {
k += N;
p[k].l = p[k].r = p[k].ts = p[k].bs = x;
for (k /= 2; k >= 1; k /= 2) {
p[k] = combine(p[2*k], p[2*k+1]);
}
}
To add/change values in the segment tree use change(k, x)
(O(log(n))
per call) where k is the position and x is the value. The maximum subarray's sum can be read from p[1].bs
(top of the tree) after each call to change
.
If you also need to find the exact indices of the subarray, you can do a recursive top-down query in O(log(n))
or a binary search of O(log^2(n))
with an iterative query.
EDIT: if we are interested in the maximum subarray of a given subarray, it's best to build a recursive top-down query. See:
https://www.quora.com/How-do-I-calculate-the-maximum-sub-segment-sum-in-a-segment-tree
So to recap, segment trees can handle this problem with changes to the data and with changes to the range we are interested in.