题目大意:给定一组数,这组数是首尾相连的,然后每次都修改这个数环的某个数值,求修改过后的这个环的最大连续子序列和,并且最大连续子序列长度不能等于整个环长。
解题思路:我们可以把环从任意一点断开,我们取从数组0位置断开拉直组成0,1,。。。。,n - 1,N个数。
当这个组数总和就是为最大连续子序列和时,满足条件的长度不等于整个环长的子序列和则为总和减去最小连续子序列。
否则,最大连续子序列为没跨越断点的最大子序列和, 和跨越了断点的的最大连续子序列和=序列总和 - 最小连续子序列。这两个里面的最大值
由于每次都要更新值,每次都得循环求值,所以我们用线段树来记录区间值,更新后只要返回根节点的最大连续子序列和就行了。这样更新查询时间就是logN的
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
struct node
{
int sum, minv, maxv, lmax, lmin, rmax, rmin, l_index, r_index;
};
const int maxn = 100010;
node tree[3 * maxn];
int n, m, array[maxn];
void create(int l, int r, int index);
void update(int index);
void modify(int index, int pos, int val);
int main()
{
int pos, val, ans;
while(scanf("%d", &n) != EOF)
{
for(int i = 0; i < n; i++)
scanf("%d", &array[i]);
create(0, n - 1, 0);
scanf("%d", &m);
for(int i = 0; i < m; i++)
{
scanf("%d %d", &pos, &val);
modify(0, pos - 1, val);
if(tree[0].sum == tree[0].maxv)
ans = tree[0].sum - tree[0].minv;
else
ans = max(tree[0].maxv, tree[0].sum - tree[0].minv);
printf("%d\n", ans);
}
}
return 0;
}
void create(int l, int r, int index)
{
tree[index].l_index = l, tree[index].r_index = r;
if(l == r)
{
tree[index].sum = tree[index].rmin = tree[index].lmin = array[l];
tree[index].lmax = tree[index].rmax = tree[index].maxv = tree[index].minv = array[l];
return;
}
int mid = (l + r) >> 1;
create(l, mid, 2 * index + 1);
create(mid + 1, r, 2 * index + 2);
update(index);
}
void update(int index)
{
tree[index].sum = tree[2 * index + 1].sum + tree[2 * index + 2].sum;
tree[index].lmin = min(tree[2 * index + 1].lmin, tree[2 * index + 1].sum + tree[2 * index + 2].lmin);
tree[index].rmin = min(tree[2 * index + 2].rmin, tree[2 * index + 2].sum + tree[2 * index + 1].rmin);
tree[index].lmax = max(tree[2 * index + 1].lmax, tree[2 * index + 1].sum + tree[2 * index + 2].lmax);
tree[index].rmax = min(tree[2 * index + 2].rmax, tree[2 * index + 2].sum + tree[2 * index + 1].rmax);
tree[index].minv = min(min(tree[2 * index + 1].minv, tree[2 * index + 2].minv), tree[2 * index + 1].rmin + tree[2 * index + 2].lmin);
tree[index].maxv = max(max(tree[2 * index + 1].maxv, tree[2 * index + 2].maxv), tree[2 * index + 1].rmax + tree[2 * index + 2].lmax);
}
void modify(int index, int pos, int val)
{
if(tree[index].l_index == tree[index].r_index)
{
tree[index].sum = tree[index].rmin = tree[index].lmin = val;
tree[index].lmax = tree[index].rmax = tree[index].maxv = tree[index].minv = val;
return;
}
int mid = (tree[index].l_index + tree[index].r_index) >> 1;
if(pos <= mid)
modify(2 * index + 1, pos, val);
else
modify(2 * index + 2, pos, val);
update(index);
}