题目链接:http://poj.org/problem?id=2750
(思考了很久也没做出来,最终还是默默去看了题解....)
思路:
sum:表示区间的和
maxNum:表示区间最大值
minNum:表示区间最小值
lmax:表示从区间左端开始的连续最大子序列
rmax:表示从区间右端开始的连续最大子序列
lmin:表示从区间左端开始的连续最小子序列
rmin:表示从区间右端开始的连续最小子序列
allmax:表示区间最大自序列
allmin:表示区间最小子序列
状态转移方程:
//当前区间的和为左右子区间之和
//当前区间的最大值为左右区间的最大值的最大值
//当前区间的最小值为左右区间的最小值的最小值
//当前区间从左端开始的连续最大子序列为左区间从左端开始的连续最大子序列与左区间的和加上右区间从左端开始的连续最大子序列的最大值
//当前区间从左端开始的连续最大子序列为右区间从右端开始的连续最大子序列与右区间的和加上左区间从右端开始的连续最大子序列的最大值
//当前区间从左端开始的连续最小子序列为左区间从左端开始的连续最小子序列与左区间的和加上右区间从左端开始的连续最小子序列的最小值
//当前区间从左端开始的连续最小子序列为右区间从右端开始的连续最小子序列与右区间的和加上左区间从右端开始的连续最小子序列的最小值
//当前区间的最大子序列为左右区间的最大子序列与左区间从右端开始的最大子序列加上右区间从左端开始的最大子序列的最大值
//当前区间的最小子序列为左右区间的最小子序列与左区间从右端开始的最小子序列加上右区间从左端开始的最小子序列的最小值
最后,还需要更新一下整个区间的最大值(因为成环):
如果区间最大子序列<区间和-区间的最小子序列
区间最大自序列=区间和-区间的最小子序列
输出的时候也需要考虑三种情况:
①全为正数:即node[1].sum==node[1].allmax
②全为负数:即node[1].sum==node[1].allmin
③非以上两种情况
具体实现详见代码:
#include<iostream> #include<cstdio> #include<cstring> #include<math.h> #include<algorithm> using namespace std; template<class T>inline T maxt(T a,T b,T c){return max(max(a,b),c);} template<class T>inline T mint(T a,T b,T c){return min(min(a,b),c);} const int INF=0x3f3f3f3f; const int maxn=100010; int T,n,m; struct segmentTree{ int l; int r; int sum; int maxNum,minNum; int lmax,rmax; int lmin,rmin; int allmax,allmin; }node[3*maxn]; void PushUp(int rt){ node[rt].sum=node[rt<<1].sum+node[rt<<1|1].sum; node[rt].maxNum=max(node[rt<<1].maxNum,node[rt<<1|1].maxNum); node[rt].minNum=min(node[rt<<1].minNum,node[rt<<1|1].minNum); node[rt].lmax=max(node[rt<<1].lmax,node[rt<<1].sum+node[rt<<1|1].lmax); node[rt].rmax=max(node[rt<<1|1].rmax,node[rt<<1|1].sum+node[rt<<1].rmax); node[rt].lmin=min(node[rt<<1].lmin,node[rt<<1].sum+node[rt<<1|1].lmin); node[rt].rmin=min(node[rt<<1|1].rmin,node[rt<<1|1].sum+node[rt<<1].rmin); node[rt].allmax=maxt(node[rt<<1].allmax,node[rt<<1|1].allmax,node[rt<<1].rmax+node[rt<<1|1].lmax); node[rt].allmin=mint(node[rt<<1].allmin,node[rt<<1|1].allmin,node[rt<<1].rmin+node[rt<<1|1].lmin); } void build(int rt,int l,int r){ node[rt].l=l; node[rt].r=r; node[rt].maxNum=0; if(l==r) return ; int mid=(l+r)>>1; build(rt<<1,l,mid); build(rt<<1|1,mid+1,r); } void Update(int rt,int l,int r,int pos,int val){ if(l==r){ node[rt].sum=val; node[rt].maxNum=node[rt].minNum=node[rt].lmax=node[rt].rmax=val; node[rt].lmin=node[rt].rmin=node[rt].allmax=node[rt].allmin=val; return ; } int mid=(l+r)>>1; if(pos<=mid) Update(rt<<1,l,mid,pos,val); else Update(rt<<1|1,mid+1,r,pos,val); PushUp(rt); } void Function(){ if(node[1].allmax<node[1].sum-node[1].allmin) node[1].allmax=node[1].sum-node[1].allmin; } void Output(){ if(node[1].sum==node[1].allmax) printf("%d\n",node[1].sum-node[1].minNum); else if(node[1].sum==node[1].allmin) printf("%d\n",node[1].maxNum); else printf("%d\n",node[1].allmax); } int main(){ #ifndef ONLINE_JUDGE freopen("test.in","r",stdin); freopen("test.out","w",stdout); #endif while(~scanf("%d",&n)){ build(1,1,n); int a,b; for(int i=1;i<=n;i++){ scanf("%d",&a); Update(1,1,n,i,a); } scanf("%d",&m); while(m--){ scanf("%d%d",&a,&b); Update(1,1,n,a,b); Function(); Output(); } } return 0; }