您的位置:首页 > 其它

poj 1750Potted Flower(线段树 区间合并 动态规划 区间求最大连续和)

2017-02-07 08:46 639 查看
Potted Flower

Time Limit: 2000MSMemory Limit: 65536K
Total Submissions: 4786Accepted: 1827
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.
Sample Input
5
3 -2 1 2 -5
4
2 -2
5 -5
2 -4
5 -1

Sample Output
4
4
3
5
问题描述:给定一个环形序列,进行在线操作,每次修改一个元素,输出环上的最大连续子列的和。出题者的简单解题报告:把环从一个地方,切断拉成一条直线,用线段树记录当前区间的非空最大子列和当前区间的非空最小子列。如果环上的数都是正整数,答案是:环上数的总和-根结点的非空最小子列;否则,答案是:max{根结点的非空最大子列,环上数的总和-根结点的非空最小子列},每次问答的复杂度是O(logN)。对于一个结点,我们要存储以下信息:
int max[MAXN<<2], min[MAXN<<2]; //结点[a, b]的最大非空连续子列和最小非空连续子列
int lmax[MAXN<<2]; //结点[a, b]包含a的最大非空连续子列
int rmax[MAXN<<2]; //结点[a, b]包含b的最大非空连续子列
int lmin[MAXN<<2];  //结点[a, b]包含a的最小非空连续子列int rmin[MAXN<<2]; //结点[a, b]包含b的最小非空连续子列
int sum[MAXN<<2]; //结点[a, b]的总和
结点[a, m],[m+1, b]分别为[a, b]的左右儿子动态规划思想由结点左右儿子的信息得到父节点的信息,设父节点下标为rt那么:状态转移方程如下:    max[rt] = max(max(max[rt<<1], max[rt<<1|1]), rmax[rt<<1]+lmax[rt<<1|1]); //求父节点的最大非空连续子列
min[rt] = min(min(min[rt<<1], min[rt<<1|1]), rmin[rt<<1]+lmin[rt<<1|1]);//求父节点的最小非空连续子列
lmax[rt] = max(lmax[rt<<1], sum[rt<<1]+lmax[rt<<1|1]);//求父节点的包含a的最大非空连续子列
rmax[rt] = max(rmax[rt<<1|1], sum[rt<<1|1]+rmax[rt<<1]);//求父节点的包含b的最大非空连续子列
lmin[rt] = min(lmin[rt<<1], sum[rt<<1]+lmin[rt<<1|1]); //求父节点的包含a的最小非空连续子列
rmin[rt] = min(rmin[rt<<1|1], sum[rt<<1|1]+rmin[rt<<1]);//求父节点的包含b的最小非空连续子列这道题的难点主要在于给出的是一个环而不是序列;所以选择一个点把环拆成序列,那么就可以把问题转化成:在一个序列中,取一段子序列,或两边都取两段序列,是权值最大;这个答案就是在这个序列里取区间的max(最大值ma,序列和sum-最小值mi);这些都可以用线段树维护;但是,这道题不允许取整段序列,所以直接这么搞是不行的;考虑什么时候会取整段序列呢,那也就是没有负数的时候(有负数就直接不取它就有了更优解);没有负数也就意味着sum==ma,于是特判就可以了#include <stdio.h>
#include <algorithm>
using namespace std;
#define size 110000
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1

int sum[size<<2],Max[size<<2],lmax[size<<2],rmax[size<<2];
int Min[size<<2],lmin[size<<2],rmin[size<<2];

void pushup(int rt)
{
sum[rt] = sum[rt<<1] + sum[rt<<1|1];
Max[rt] = max(max(Max[rt<<1],Max[rt<<1|1]), lmax[rt<<1|1]+rmax[rt<<1]);
Min[rt] = min(min(Min[rt<<1],Min[rt<<1|1]), lmin[rt<<1|1]+rmin[rt<<1]);
lmax[rt] = max(lmax[rt<<1],sum[rt<<1] + lmax[rt<<1|1]);
lmin[rt] = min(lmin[rt<<1],sum[rt<<1] + lmin[rt<<1|1]);
rmax[rt] = max(rmax[rt<<1|1],sum[rt<<1|1] + rmax[rt<<1]);
rmin[rt] = min(rmin[rt<<1|1],sum[rt<<1|1] + rmin[rt<<1]);
}
void build( int l, int r, int rt)
{
if( l == r)
{
scanf("%d", &sum[rt]);
Max[rt] = lmax[rt] = rmax[rt] = sum[rt];
Min[rt] = lmin[rt] = rmin[rt] = sum[rt];
return;
}
int m = (l + r) >> 1;
build(lson);
build(rson);
pushup(rt);
}
void updata(int p,int c,int l,int r,int rt)
{
if( l == r)
{
sum[rt] = c;
Max[rt] = lmax[rt] = rmax[rt] = sum[rt];
Min[rt] = lmin[rt] = rmin[rt] = sum[rt];
return;
}
int m = (l + r)>>1;
if( p <= m ) updata(p, c, lson);
else updata(p, c, rson);
pushup(rt);
}
int main()
{
int n;
while(~scanf("%d", &n))
{
build(1, n, 1);
int m;
scanf("%d", &m);
while(m--)
{
int a, b;scanf("%d%d", &a, &b);
updata(a, b, 1, n, 1);
if(sum[1] == Max[1])//如果为非负数
printf("%d\n", sum[1] - Min[1]);
else printf("%d\n", max(sum[1] - Min[1], Max[1]));
}

}
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: