pku2750 Potted Flower
问题描述:给定一个环形序列,进行在线操作,每次修改一个元素,输出环上的最大连续子段的和。
分析:涉及到线段树的以下操作:维护区间左边开始的连续最大子段和,从右边开始的连续最大子段和,区间的最大子段和
#include <iostream>
using namespace std;
#define MAXN 100005
#define Min(a,b) (a<b?a:b)
#define Max(a,b) (a>b?a:b)
int n,m;
struct Node{
int l,r,mx,lmx,rmx,mn,lmn,rmn,sum,mnnum;
bool allpos;
}nod[3*MAXN];
void buildtree(int u,int l,int r){
nod[u].l=l;
nod[u].r=r;
nod[u].lmx=INT_MIN;
nod[u].rmx=INT_MIN;
nod[u].mx=INT_MIN;
nod[u].lmn=INT_MAX;
nod[u].rmn=INT_MAX;
nod[u].mn=INT_MAX;
nod[u].sum=0;
nod[u].mnnum=INT_MAX;
nod[u].allpos=true;
if(r==l)
return;
buildtree(2*u,l,(l+r)/2);
buildtree(2*u+1,(l+r)/2+1,r);
}
void insert(int u,int l,int r,int val){
if(nod[u].l==l && nod[u].r==r){
nod[u].mx=val;
nod[u].lmx=val;
nod[u].rmx=val;
nod[u].mn=val;
nod[u].lmn=val;
nod[u].rmn=val;
nod[u].sum=val;
nod[u].mnnum=val;
if(val>=0)
nod[u].allpos=true;
else
nod[u].allpos=false;
return;
}
if(l<=nod[2*u].r)
insert(2*u,l,r,val);
if(r>=nod[2*u+1].l)
insert(2*u+1,l,r,val);
nod[u].allpos=nod[2*u].allpos && nod[2*u+1].allpos;
nod[u].sum=nod[2*u].sum+nod[2*u+1].sum;
nod[u].lmx=Max(nod[2*u].lmx,nod[2*u].sum+nod[2*u+1].lmx);
nod[u].rmx=Max(nod[2*u+1].rmx,nod[2*u+1].sum+nod[2*u].rmx);
//nod[u].mx=Max(nod[2*u].rmx+nod[2*u+1].lmx,nod[2*u].mx,nod[2*u+1].mx);
nod[u].mx=nod[2*u].rmx+nod[2*u+1].lmx;
nod[u].mx=Max(nod[u].mx,nod[2*u].mx);
nod[u].mx=Max(nod[u].mx,nod[2*u+1].mx);
nod[u].lmn=Min(nod[2*u].lmn,nod[2*u].sum+nod[2*u+1].lmn);
nod[u].rmn=Min(nod[2*u+1].rmn,nod[2*u+1].sum+nod[2*u].rmn);
//nod[u].mn=Min(nod[2*u].rmn+nod[2*u+1].lmn,nod[2*u].mn,nod[2*u+1].mn);
nod[u].mn=nod[2*u].rmn+nod[2*u+1].lmn;
nod[u].mn=Min(nod[u].mn,nod[2*u].mn);
nod[u].mn=Min(nod[u].mn,nod[2*u+1].mn);
nod[u].mnnum=Min(nod[2*u].mnnum,nod[2*u+1].mnnum);
//环内最小的数,当环内元素全部为非负时用到
}
int main(){
int i,pos,a,mn;
while(scanf("%d",&n)!=EOF){
buildtree(1,1,n);
mn=INT_MAX;
for(i=1;i<=n;i++){
scanf("%d",&a);
if(a<mn)
mn=a;
insert(1,i,i,a);
}
scanf("%d",&m);
for(i=0;i<m;i++){
scanf("%d%d",&pos,&a);
if(a<mn)
mn=a;
insert(1,pos,pos,a);
if(nod[1].allpos)//当环内元素全为非负时
printf("%d\n",nod[1].sum-nod[1].mnnum);
//解为环和去掉最小的一个元素
else
printf("%d\n",Max(nod[1].sum-nod[1].mn,nod[1].mx));
//解为环和减去最小子列和最大子列两者中的较大值
}
}
return 0;
}
using namespace std;
#define MAXN 100005
#define Min(a,b) (a<b?a:b)
#define Max(a,b) (a>b?a:b)
int n,m;
struct Node{
int l,r,mx,lmx,rmx,mn,lmn,rmn,sum,mnnum;
bool allpos;
}nod[3*MAXN];
void buildtree(int u,int l,int r){
nod[u].l=l;
nod[u].r=r;
nod[u].lmx=INT_MIN;
nod[u].rmx=INT_MIN;
nod[u].mx=INT_MIN;
nod[u].lmn=INT_MAX;
nod[u].rmn=INT_MAX;
nod[u].mn=INT_MAX;
nod[u].sum=0;
nod[u].mnnum=INT_MAX;
nod[u].allpos=true;
if(r==l)
return;
buildtree(2*u,l,(l+r)/2);
buildtree(2*u+1,(l+r)/2+1,r);
}
void insert(int u,int l,int r,int val){
if(nod[u].l==l && nod[u].r==r){
nod[u].mx=val;
nod[u].lmx=val;
nod[u].rmx=val;
nod[u].mn=val;
nod[u].lmn=val;
nod[u].rmn=val;
nod[u].sum=val;
nod[u].mnnum=val;
if(val>=0)
nod[u].allpos=true;
else
nod[u].allpos=false;
return;
}
if(l<=nod[2*u].r)
insert(2*u,l,r,val);
if(r>=nod[2*u+1].l)
insert(2*u+1,l,r,val);
nod[u].allpos=nod[2*u].allpos && nod[2*u+1].allpos;
nod[u].sum=nod[2*u].sum+nod[2*u+1].sum;
nod[u].lmx=Max(nod[2*u].lmx,nod[2*u].sum+nod[2*u+1].lmx);
nod[u].rmx=Max(nod[2*u+1].rmx,nod[2*u+1].sum+nod[2*u].rmx);
//nod[u].mx=Max(nod[2*u].rmx+nod[2*u+1].lmx,nod[2*u].mx,nod[2*u+1].mx);
nod[u].mx=nod[2*u].rmx+nod[2*u+1].lmx;
nod[u].mx=Max(nod[u].mx,nod[2*u].mx);
nod[u].mx=Max(nod[u].mx,nod[2*u+1].mx);
nod[u].lmn=Min(nod[2*u].lmn,nod[2*u].sum+nod[2*u+1].lmn);
nod[u].rmn=Min(nod[2*u+1].rmn,nod[2*u+1].sum+nod[2*u].rmn);
//nod[u].mn=Min(nod[2*u].rmn+nod[2*u+1].lmn,nod[2*u].mn,nod[2*u+1].mn);
nod[u].mn=nod[2*u].rmn+nod[2*u+1].lmn;
nod[u].mn=Min(nod[u].mn,nod[2*u].mn);
nod[u].mn=Min(nod[u].mn,nod[2*u+1].mn);
nod[u].mnnum=Min(nod[2*u].mnnum,nod[2*u+1].mnnum);
//环内最小的数,当环内元素全部为非负时用到
}
int main(){
int i,pos,a,mn;
while(scanf("%d",&n)!=EOF){
buildtree(1,1,n);
mn=INT_MAX;
for(i=1;i<=n;i++){
scanf("%d",&a);
if(a<mn)
mn=a;
insert(1,i,i,a);
}
scanf("%d",&m);
for(i=0;i<m;i++){
scanf("%d%d",&pos,&a);
if(a<mn)
mn=a;
insert(1,pos,pos,a);
if(nod[1].allpos)//当环内元素全为非负时
printf("%d\n",nod[1].sum-nod[1].mnnum);
//解为环和去掉最小的一个元素
else
printf("%d\n",Max(nod[1].sum-nod[1].mn,nod[1].mx));
//解为环和减去最小子列和最大子列两者中的较大值
}
}
return 0;
}