http://poj.org/problem?id=2750
Description
The little cat takes over the management of a new park. There is a large circular statue in the center of the park, surrounded by N pots of flowers. Each potted flower will be assigned to an integer number (possibly negative) denoting how attractive it is. See the following graph as an example:
(Positions of potted flowers are assigned to index numbers in the range of 1 ... N. The i-th pot and the (i + 1)-th pot are consecutive for any given i (1 <= i < N), and 1st pot is next to N-th pot in addition.)
The board chairman informed the little cat to construct "ONE arc-style cane-chair" for tourists having a rest, and the sum of attractive values of the flowers beside the cane-chair should be as large as possible. You should notice that a cane-chair cannot be a total circle, so the number of flowers beside the cane-chair may be 1, 2, ..., N - 1, but cannot be N. In the above example, if we construct a cane-chair in the position of that red-dashed-arc, we will have the sum of 3+(-2)+1+2=4, which is the largest among all possible constructions.
Unluckily, some booted cats always make trouble for the little cat, by changing some potted flowers to others. The intelligence agency of little cat has caught up all the M instruments of booted cats' action. Each instrument is in the form of "A B", which means changing the A-th potted flowered with a new one whose attractive value equals to B. You have to report the new "maximal sum" after each instruction.
Input
There will be a single test data in the input. You are given an integer N (4 <= N <= 100000) in the first input line.
The second line contains N integers, which are the initial attractive value of each potted flower. The i-th number is for the potted flower on the i-th position.
A single integer M (4 <= M <= 100000) in the third input line, and the following M lines each contains an instruction "A B" in the form described above.
Restriction: All the attractive values are within [-1000, 1000]. We guarantee the maximal sum will be always a positive integer.
Output
For each instruction, output a single line with the maximum sum of attractive values for the optimum cane-chair.
题意:环形动态最大连续最大和,选的区间不能是整个环。
思路:《训练指南》有一道类似的题。
环形的话,要么就当成1~n的线段,要么跨越1和n。
首先,分情况,如果整个区间全都是正数,那么答案就是整个区间之和减去区间最小连续和
否则,答案就是min{最大连续和,区间和减去最小连续和},一定不会包含整个区间。
维护动态区间和,最大、最小连续和用线段树+类似分治/DP的思想
维护maxv,minv;lmax,lmin;rmax,rmin
一个结点的最大连续和要么在左区间或者右区间,要么跨越左右区间,用左区间的右边最大部分+右区间的左边最大部分
左区间和右区间分治推法类似。
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
#define maxn (100000+100)
int n,q,a[maxn];
int sumv[maxn*4],maxv[maxn*4],minv[maxn*4],lmax[maxn*4],lmin[maxn*4],rmax[maxn*4],rmin[maxn*4];
int nega_num;
int Max(int a,int b,int c){return max(max(a,b),c);}
int Min(int a,int b,int c){return min(min(a,b),c);}
void build(int o,int l,int r)
{
if(l==r)sumv[o]=maxv[o]=minv[o]=lmax[o]=lmin[o]=rmax[o]=rmin[o]=a[l];
else
{
int m=(l+r)/2,lc=o*2,rc=o*2+1;
build(o*2,l,m);build(o*2+1,m+1,r);
sumv[o]=sumv[lc]+sumv[rc];
maxv[o]=Max(maxv[lc],maxv[rc],rmax[lc]+lmax[rc]);
minv[o]=Min(minv[lc],minv[rc],rmin[lc]+lmin[rc]);
lmax[o]=max(lmax[lc],sumv[lc]+lmax[rc]);
lmin[o]=min(lmin[lc],sumv[lc]+lmin[rc]);
rmax[o]=max(rmax[rc],sumv[rc]+rmax[lc]);
rmin[o]=min(rmin[rc],sumv[rc]+rmin[lc]);
}
}
void maintain(int o,int l,int r)
{
int m=(l+r)/2,lc=o*2,rc=o*2+1;
sumv[o]=sumv[lc]+sumv[rc];
maxv[o]=Max(maxv[lc],maxv[rc],rmax[lc]+lmax[rc]);
minv[o]=Min(minv[lc],minv[rc],rmin[lc]+lmin[rc]);
lmax[o]=max(lmax[lc],sumv[lc]+lmax[rc]);
lmin[o]=min(lmin[lc],sumv[lc]+lmin[rc]);
rmax[o]=max(rmax[rc],sumv[rc]+rmax[lc]);
rmin[o]=min(rmin[rc],sumv[rc]+rmin[lc]);
}
int p,v;
void update(int o,int l,int r)
{
if(l==r)sumv[o]=maxv[o]=minv[o]=lmax[o]=lmin[o]=rmax[o]=rmin[o]=v;
else
{
int m=(l+r)/2,lc=o*2,rc=o*2+1;
if(p<=m)update(lc,l,m);
else update(rc,m+1,r);
maintain(o,l,r);
}
}
int query(int o,int l,int r)
{
if(nega_num==0)return sumv[o]-minv[o];
return max(maxv[o],sumv[o]-minv[o]);
}
int main()
{
// freopen("input.in","r",stdin);
cin>>n;
for(int i=1;i<=n;i++)scanf("%d",&a[i]),nega_num+=(a[i]<0);
build(1,1,n);
cin>>q;
while(q--)
{
scanf("%d%d",&p,&v);
if(a[p]<0)nega_num--;
a[p]=v;
if(a[p]<0)nega_num++;
update(1,1,n);
cout<<query(1,1,n)<<endl;
}
return 0;
}