poj2750--Potted Flower(线段树)

题目链接:点击打开链接

题目大意:给出n个数排成一个环。求环的最大连续子序列,不能是总序列

建一个线段树来求最大子序列假设仅仅是一个序列。那么求最大连续子序列非常easy,可是假设是一个环,那就要考虑断点的问题,由于结果可能是由左边一部分+右边一部分,这种结果用线段树没法统计到,所以须要转换一下:

求最大连续子序列 = 总和 - 最小连续子序列

那么题目就非常easy了,要统计出每一段的最大连续子序列,最小连续子序列和总和。

sum[rt] = sum[rt<<1] + sum[rt<<1|1] ;

max1[rt] = max( max(max1[rt<<1],max1[rt<<1|1]),rmax1[rt<<1]+lmax1[rt<<1|1] ) ; 最大连续子序列

min1[rt] = min( min(min1[rt<<1],min1[rt<<1|1]),rmin1[rt<<1]+lmin1[rt<<1|1] ) ; 最小连续子序列

lmax1[rt] = max(lmax1[rt<<1],sum[rt<<1]+lmax1[rt<<1|1]) ; 以左側开头的最大子序列

lmin1[rt] = min(lmin1[rt<<1],sum[rt<<1]+lmin1[rt<<1|1]) ; 以左側开头的最小子序列

rmax1[rt] = max(rmax1[rt<<1|1],sum[rt<<1|1]+rmax1[rt<<1]) ; 以右側开头的最大子序列

rmin1[rt] = min(rmin1[rt<<1|1],sum[rt<<1|1]+rmin1[rt<<1]) ; 以右側开头的最小子序列

有由于不能是所有的序列,那么能够分开考虑,假设全都是整数,最大连续子序列是总和,那么结果应该是总和-最小连续子序列,假设全是负数。那么结果应该是最大连续子序列,其它的为 max(max1[1],sum[1]-min1[1]))

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;
#define root 1,n,1
#define int_rt int l,int r,int rt
#define lson l,(l+r)/2,rt<<1
#define rson (l+r)/2+1,r,rt<<1|1
int cl[1000000] , sum[1000000] ;
int max1[1000000] , min1[1000000] ;
int lmax1[1000000] , lmin1[1000000] ;
int rmax1[1000000] , rmin1[1000000] ;
void push_up(int rt) {
    sum[rt] = sum[rt<<1] + sum[rt<<1|1] ;
    max1[rt] = max( max(max1[rt<<1],max1[rt<<1|1]),rmax1[rt<<1]+lmax1[rt<<1|1] ) ;
    min1[rt] = min( min(min1[rt<<1],min1[rt<<1|1]),rmin1[rt<<1]+lmin1[rt<<1|1] ) ;
    lmax1[rt] = max(lmax1[rt<<1],sum[rt<<1]+lmax1[rt<<1|1]) ;
    lmin1[rt] = min(lmin1[rt<<1],sum[rt<<1]+lmin1[rt<<1|1]) ;
    rmax1[rt] = max(rmax1[rt<<1|1],sum[rt<<1|1]+rmax1[rt<<1]) ;
    rmin1[rt] = min(rmin1[rt<<1|1],sum[rt<<1|1]+rmin1[rt<<1]) ;
}
void creat(int_rt) {
    if( l == r ) {
        scanf("%d", &cl[rt]) ;
        sum[rt] = max1[rt] = min1[rt] = lmax1[rt] = lmin1[rt] = rmax1[rt] = rmin1[rt] = cl[rt] ;
        return ;
    }
    creat(lson) ;
    creat(rson) ;
    push_up(rt) ;
}
void update(int k,int s,int_rt) {
    if( l == r ) {
        cl[rt] = s ;
        sum[rt] = max1[rt] = min1[rt] =  lmax1[rt] = lmin1[rt] = rmax1[rt] = rmin1[rt] = cl[rt] ;
        return ;
    }
    if( (l+r)/2 >= k )
        update(k,s,lson) ;
    else
        update(k,s,rson) ;
    push_up(rt) ;
}
int main() {
    int n , m , i , k , s ;
    while( scanf("%d", &n) != EOF ) {
        creat(root) ;
        scanf("%d", &m) ;
        while( m-- ) {
            scanf("%d %d", &k, &s) ;
            update(k,s,root) ;
            if( max1[1] == sum[1] )
                printf("%d\n", sum[1]-min1[1]) ;
            else if( min1[1] == sum[1] )
                printf("%d\n", max1[1]) ;
            else
                printf("%d\n", max(max1[1],sum[1]-min1[1])) ;
        }
    }
    return 0 ;
}
时间: 2024-10-21 02:11:55

poj2750--Potted Flower(线段树)的相关文章

poj 2750 Potted Flower(线段树区间合并)

http://poj.org/problem?id=2750 有n个数围成一个圈,每次可以将a位置上的数变为b,对每个操作,输出区间的最大连续子段和,连续的子段长度不能超过n. 区间合并问题,因为是求连续子段的和.先把圈从1和n之间断开,变为一条链,先在链上求最长连续的和.这个最长连续的和取左节点最长连续和,右节点最长连续和,左节点从右边数最大连续和加上右节点从左边数最大连续和三者的最大值. 特殊情况就是当区间全为正的时候,最长连续和等于1-n的和,这违背题意,它应该等于区间总和减去区间内最小连

poj-2750 Potted Flower

题意: 给出一个n个结点的环,在这个环上取一段区间(不能是整个环),使权值和最大: m次修改某个结点权值,每次修改后输出最大值: n,m<=100000: 题解: 这道题的难点主要在于给出的是一个环而不是序列: 所以选择一个点把环拆成序列,那么就可以把问题转化成: 在一个序列中,取一段子序列,或两边都取两段序列,是权值最大: 这个答案就是在这个序列里取区间的max(最大值ma,序列和sum-最小值mi): 这些都可以用线段树维护: 但是,这道题不允许取整段序列,所以直接这么搞是不行的: 考虑什么

【POJ 2750】 Potted Flower(线段树套dp)

[POJ 2750] Potted Flower(线段树套dp) Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4566   Accepted: 1739 Description The little cat takes over the management of a new park. There is a large circular statue in the center of the park, surrou

POJ 题目2750 Potted Flower(线段树求环型区间中连续区间的最大和)

Potted Flower Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4470   Accepted: 1698 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 f

POJ 2750 Potted Flower (单点修改求线段树上最大子序列和)

题目大意: 在一个序列上每次修改一个值,然后求出它的最大的子序列和. 思路分析: 首先我们不考虑不成环的问题.那就是直接求每个区间的最大值就好了. 但是此处成环,那么看一下下面样例. 5 1 -2 -3 4 5 那么你会发现 max = sum - min 也就是和减去最小区间和也可以得到. 所以我们最后要得到的就是两个东西.注意题目中说的不能全部取得.所以还要判断一下max 是不是等于 sum的. #include <cstdio> #include <iostream> #in

poj 2750(线段树的动态规划)

Potted Flower Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4186   Accepted: 1581 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 f

POJ 2570 线段树

Potted Flower Time Limit: 2000 MS Memory Limit: 65536 KB 64-bit integer IO format: %I64d , %I64u Java class name: Main [Submit] [Status] [Discuss] Description The little cat takes over the management of a new park. There is a large circular statue in

ACM——敌兵布阵(经典的线段树)

Description Lily 特 别喜欢养花,但是由于她的花特别多,所以照料这些花就变得不太容易.她把她的花依次排成一行,每盆花都有一个美观值.如果Lily把某盆花照料的好的话, 这盆花的美观值就会上升,如果照料的不好的话,这盆花的美观值就会下降.有时,Lily想知道某段连续的花的美观值之和是多少,但是,Lily的算术不是 很好,你能快速地告诉她结果吗? Input 第一行一个整数T,表示有T组测试数据. 每组测试数据的第一行为一个正整数N(N<=50000),表示Lily有N盆花.接下来有

HDU 4614 Vases and Flowers(线段树区间更新+二分)

Problem Description Alice is so popular that she can receive many flowers everyday. She has N vases numbered from 0 to N-1. When she receive some flowers, she will try to put them in the vases, one flower in one vase. She randomly choose the vase A a