题意 : 很多花盆组成的圆圈,每个花盆都有一个值,给你两个数a,b代表a位置原来的数换成b,然后让你从圈里找出连续的各花盆之和,要求最大的。
思路 :这个题比较那啥,差不多可以用DP的思想来解决这个问题,你在某个地方将这个环断开,因为线段树无法建成环形的。然后再去找那个最大值。将这个序列分成两部分,先求左边的最大连续和a,再求右边连续和b,但是由于他们中间相连的那部分,就是左部分的最右边的连续最大和x加上右部分的最左边的连续最大和y加起来可能比ab都大,但分开的话可能并没有a或b大。所以要进行区间合并,将y并到左边去,或者将x并到右边去,但本身那个边界不变
#include <iostream>
#include <stdio.h>
#include <string.h> using namespace std; const int maxn = ;
int maxx[maxn << ],minn[maxn << ] ;
int lmax[maxn << ],rmax[maxn << ] ;
int lmin[maxn << ],rmin[maxn << ] ;
int sum[maxn << ] ; void dp(int v)
{
int l = v << ,r = l+;
sum[v] = sum[l]+sum[r] ;
maxx[v] = max(max(maxx[l],maxx[r]),lmax[r] + rmax[l]) ;
minn[v] = min(min(minn[l],minn[r]),lmin[r] + rmin[l]) ;
lmax[v] = max(lmax[l],sum[l]+lmax[r]) ;
rmax[v] = max(rmax[r],sum[r]+rmax[l]) ;
lmin[v] = min(lmin[l],sum[l]+lmin[r]) ;
rmin[v] = min(rmin[r],sum[r]+rmin[l]) ;
}
void build(int v,int l,int r)
{
if(l == r)
{
scanf("%d",&sum[v]) ;
maxx[v] = minn[v] = lmax[v] = rmax[v] = lmin[v] = rmin[v] = sum[v] ;
return ;
}
int mid = (l+r) >> ;
build(v*,l,mid) ;
build(v*+,mid+,r) ;
dp(v) ;
}
void update(int v,int l,int r,int num,int value)
{
if(l == r)
{
sum[v] = maxx[v] = minn[v] = value ;
lmax[v] = rmax[v] = lmin[v] = rmin[v] = value ;
return ;
}
int mid = (l+r) >> ;
if(mid >= num) update(v*,l,mid,num,value) ;
else update(v*+,mid+,r,num,value) ;
dp(v) ;
} int main()
{
int n ;
while(~scanf("%d",&n))
{
build(,,n) ;
int m ;
scanf("%d",&m) ;
while(m--)
{
int x,y ;
int ans ;
scanf("%d %d",&x,&y) ;
update(,,n,x,y) ;
if(sum[] == maxx[])
ans = sum[]-minn[] ;
else
ans = max(maxx[], sum[]-minn[]) ;
printf("%d\n",ans) ;
}
}
return ;
}