这个题关键是这一段代码
struct node{
int l, r;
int lmaxs, rmaxs, maxsum;
int lmins, rmins, minsum;
int max, min;
int sum;
}Tree[N * 4];
分别表示左起连续最大值,右起连续最大值,最大连续值,以及对应的最小值。还有是最大数,最小数,sum表示区间和。
全为正和全为负的情况,正则取sum - min, 负则取max;
其他情况,最大连续值要么在区间内,要么跨过n。前者好考虑,如果是后者,那么没包含的区间一定是最小连续区间。
为什么呢?这样证明:首先这个区间两端均为负数且区间和为负数,这个很显然,如果有另外一个区间sum比它还小(显然为负),那么最大连续区间完全可以舍弃那个区间而将它包含进来。这样便得证。
代码704ms
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#define L(t) t << 1
#define R(t) t << 1 | 1
#define N 100010
using namespace std;
int array[N];
int poscnt, negcnt;
struct node{
int l, r;
int lmaxs, rmaxs, maxsum;
int lmins, rmins, minsum;
int max, min;
int sum;
}Tree[N * 4];
void update_sum(int x)
{
if (Tree[x].l == Tree[x].r)return;
Tree[x].sum = Tree[L(x)].sum + Tree[R(x)].sum;
Tree[x].lmins = min(Tree[L(x)].lmins, Tree[L(x)].sum + Tree[R(x)].lmins);
Tree[x].rmins = min(Tree[R(x)].rmins, Tree[R(x)].sum + Tree[L(x)].rmins) ;
Tree[x].lmaxs = max(Tree[L(x)].lmaxs, Tree[L(x)].sum + Tree[R(x)].lmaxs);
Tree[x].rmaxs = max(Tree[R(x)].rmaxs, Tree[R(x)].sum + Tree[L(x)].rmaxs);
Tree[x].maxsum = max(max(Tree[L(x)].maxsum, Tree[R(x)].maxsum), Tree[L(x)].rmaxs + Tree[R(x)].lmaxs);
Tree[x].minsum = min(min(Tree[L(x)].minsum, Tree[R(x)].minsum), Tree[L(x)].rmins + Tree[R(x)].lmins);
Tree[x].min = min(Tree[L(x)].min, Tree[R(x)].min);
Tree[x].max = max(Tree[L(x)].max, Tree[R(x)].max);
}
void build(int l, int r, int x)
{
Tree[x].l = l;
Tree[x].r = r;
if (l == r)
{
Tree[x].maxsum = Tree[x].minsum = Tree[x].sum = array[l];
Tree[x].lmaxs = Tree[x].rmaxs = Tree[x].sum;
Tree[x].lmins = Tree[x].rmins = Tree[x].sum;
Tree[x].max = Tree[x].min = Tree[x].sum;
return;
}
int mid = (l + r) /2;
build(l, mid, L(x));
build(mid + 1, r, R(x));
update_sum(x);
}
void update(int nu, int val, int x)
{
if (Tree[x].l == Tree[x].r)
{
if (Tree[x].sum >= 0 && val < 0)poscnt--, negcnt++;
else if (Tree[x].sum < 0 && val >= 0)poscnt++, negcnt--;
Tree[x].maxsum = Tree[x].minsum = Tree[x].sum = val;
Tree[x].lmaxs = Tree[x].rmaxs = Tree[x].sum;
Tree[x].lmins = Tree[x].rmins = Tree[x].sum;
Tree[x].max = Tree[x].min = Tree[x].sum;
return;
}
int mid = (Tree[x].l + Tree[x].r) /2;
if (nu <= mid)
{
update(nu, val, L(x));
update_sum(L(x));
}
else
{
update(nu, val, R(x));
update_sum(R(x));
}
update_sum(x);
}
int main()
{
// FILE* fp = fopen("in.txt", "r");
int n, m;
scanf( "%d", &n);
poscnt = negcnt = 0;
for (int i = 1; i <= n; i++)
{
scanf( "%d", array + i);
if (array[i] < 0)negcnt++;
else poscnt++;
}
scanf( "%d", &m);
build(1, n, 1);
int a, b;
while (m--)
{
scanf( "%d %d", &a, &b);
update(a, b, 1);
int ans;
if (poscnt == n)ans = Tree[1].sum - Tree[1].min;
else if (poscnt == 0)ans = Tree[1].max;
else
{
ans = max(Tree[1].maxsum, Tree[1].sum - Tree[1].minsum);
}
printf("%d\n", ans);
}
//getchar();
return 0;
}