题意:给定一个环形序列,可以进行在线操作,每次修改一个其中元素。每次修改之后立即输出环上的最大连续子序列的和,要求子序列的长度不得为n,也即不能是整个环。
思路:比较复杂的线段树(http://blog.youkuaiyun.com/non_cease/article/details/7437690)把环从一个地方切断拉成一条直线(最直观当然是从n~1之间切断),用线段树记录当前区间的非空最大子列和当前区间的非空最小子列。如果环上的数都是正整数,答案是:环上数的总和-根结点的非空最小子列;否则,答案是:max{根结点的非空最大子列,环上数的总和-根结点的非空最小子列},每次问答的复杂度是O(logN)。
结点内记录的内容比较多,需要记录序列的从左向右最大连续序列值lmax,从右往左的最大连续序列值rmax,和从左向右最小连续序列值lmin,从右往左的最小连续序列值rmin,和每个序列的最大连续序列值semax和最小连续序列值semin,以及在当前区域的和sum。更新起来也就比较显然。
#include <stdio.h>
#include <string.h>
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#define N 100005
struct node{
int sum;
int semax,semin;
int lmax,rmax;
int lmin,rmin;
}t[N<<2];
int n,m;
int mid(int a,int b){
return (a+b)>>1;
}
void update(int r){
int lson,rson;
lson = r<<1;
rson = lson+1;
t[r].sum = t[lson].sum + t[rson].sum;
t[r].semax = max(max(t[lson].semax , t[rson].semax), t[lson].rmax+t[rson].lmax);
t[r].semin = min(min(t[lson].semin , t[rson].semin), t[lson].rmin+t[rson].lmin);
t[r].lmax = max(t[lson].lmax, t[lson].sum+t[rson].lmax);
t[r].lmin = min(t[lson].lmin, t[lson].sum+t[rson].lmin);
t[r].rmax = max(t[rson].rmax, t[rson].sum+t[lson].rmax);
t[r].rmin = min(t[rson].rmin, t[rson].sum+t[lson].rmin);
}
void build(int r,int a,int b){
int k = mid(a,b);
if(a == b){
scanf("%d",&t[r].sum);
t[r].semax = t[r].semin = t[r].lmax = t[r].lmin = t[r].rmax = t[r].rmin = t[r].sum;
return;
}
build(r*2, a, k);
build(r*2+1, k+1, b);
update(r);
}
void alter(int x,int y,int r,int a,int b){
int k=mid(a,b);
if(a==x && b==x){
t[r].sum = y;
t[r].semax = t[r].semin = t[r].lmax = t[r].lmin = t[r].rmax = t[r].rmin = t[r].sum;
return;
}
if(x<=k)
alter(x, y, r*2, a, k);
else
alter(x, y, r*2+1, k+1, b);
update(r);
}
int main(){
int i,x,y;
scanf("%d",&n);
build(1,1,n);
scanf("%d",&m);
for(i = 0;i<m;i++){
scanf("%d %d",&x,&y);
alter(x,y,1,1,n);
if(t[1].sum == t[1].semax)
printf("%d\n",t[1].sum-t[1].semin);
else
printf("%d\n",max(t[1].sum-t[1].semin, t[1].semax));
}
return 0;
}
本文介绍了一种使用线段树解决环形序列最大连续子序列和问题的方法。通过将环形序列转换为线性序列,并利用线段树记录区间内的最大与最小连续子序列和,实现了高效的在线修改与查询。

被折叠的 条评论
为什么被折叠?



