题意:给你一个环,实时更新环上某个结点的值,让你找出连续和的最大值(不能包括所有数)
分析:线段树的区间合并
参考代码:
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
#define ls rt<<1
#define rs rt<<1|1
const int maxn = 1e6+5;
int n,m;
int val[maxn];
struct Node{
int l,r;
int sum;
int lmax,rmax,maxsum;
int lmin,rmin,minsum;
};
Node st[maxn<<2];
void PushUp( int rt)
{
st[rt].sum = st[ls].sum+st[rs].sum;
st[rt].lmax = max(st[ls].lmax,st[ls].sum+st[rs].lmax);
st[rt].rmax = max(st[ls].rmax+st[rs].sum,st[rs].rmax);
st[rt].maxsum = max(max(st[ls].maxsum,st[rs].maxsum),st[ls].rmax+st[rs].lmax);
st[rt].lmin = min(st[ls].lmin,st[ls].sum+st[rs].lmin);
st[rt].rmin = min(st[ls].rmin+st[rs].sum,st[rs].rmin);
st[rt].minsum = min(min(st[ls].minsum,st[rs].minsum),st[ls].rmin+st[rs].lmin);
}
void Build( int l, int r, int rt)
{
st[rt].l = l;
st[rt].r = r;
if( l == r)
{
st[rt].sum = val[l];
st[rt].lmax = st[rt].rmax = st[rt].maxsum = val[l];
st[rt].lmin = st[rt].rmin = st[rt].minsum = val[l];
return;
}
int mid = (l+r)>>1;
Build(l,mid,ls);
Build(mid+1,r,rs);
PushUp(rt);
}
void Update( int rt, int pos, int val)
{
if( st[rt].l == st[rt].r && st[rt].l == pos)
{
st[rt].sum = val;
st[rt].lmax = st[rt].rmax = st[rt].maxsum = val;
st[rt].lmin = st[rt].rmin = st[rt].minsum = val;
return;
}
int mid = (st[rt].l+st[rt].r)>>1;
if( pos <= mid)
Update(ls,pos,val);
else
Update(rs,pos,val);
PushUp(rt);
}
int query()
{
if( st[1].sum == st[1].maxsum)
return st[1].sum-st[1].minsum;
else
return max(st[1].maxsum,st[1].sum-st[1].minsum);
}
int main()
{
while( ~scanf("%d",&n))
{
for( int i = 1; i <= n; i++)
scanf("%d",&val[i]);
Build( 1,n,1);
scanf("%d",&m);
while( m--)
{
int pos,num;
scanf("%d%d",&pos,&num);
Update(1,pos,num);
printf("%d\n",query());
}
}
return 0;
}