poj 2750 Potted Flower(线段树#8)

这个题关键是这一段代码

struct node{
        int l, r;
        int lmaxs, rmaxs, maxsum;
        int lmins, rmins, minsum; 
        int max, min; 
        int sum; 
}Tree[N * 4];

分别表示左起连续最大值,右起连续最大值,最大连续值,以及对应的最小值。还有是最大数,最小数,sum表示区间和。

全为正和全为负的情况,正则取sum - min, 负则取max;

其他情况,最大连续值要么在区间内,要么跨过n。前者好考虑,如果是后者,那么没包含的区间一定是最小连续区间。

为什么呢?这样证明:首先这个区间两端均为负数且区间和为负数,这个很显然,如果有另外一个区间sum比它还小(显然为负),那么最大连续区间完全可以舍弃那个区间而将它包含进来。这样便得证。

代码704ms

#include <cstdio>
#include <cstdlib>
#include <algorithm> 
#define L(t) t << 1
#define R(t) t << 1 | 1 
#define N 100010
using namespace std;
int array[N]; 
int poscnt, negcnt; 

struct node{
        int l, r;
        int lmaxs, rmaxs, maxsum;
        int lmins, rmins, minsum; 
        int max, min; 
        int sum; 
}Tree[N * 4];

void update_sum(int x)
{
        if (Tree[x].l == Tree[x].r)return; 
        Tree[x].sum = Tree[L(x)].sum + Tree[R(x)].sum;
        Tree[x].lmins = min(Tree[L(x)].lmins, Tree[L(x)].sum + Tree[R(x)].lmins); 
        Tree[x].rmins = min(Tree[R(x)].rmins, Tree[R(x)].sum + Tree[L(x)].rmins) ;
        Tree[x].lmaxs = max(Tree[L(x)].lmaxs, Tree[L(x)].sum + Tree[R(x)].lmaxs);
        Tree[x].rmaxs = max(Tree[R(x)].rmaxs, Tree[R(x)].sum + Tree[L(x)].rmaxs);
        Tree[x].maxsum = max(max(Tree[L(x)].maxsum, Tree[R(x)].maxsum), Tree[L(x)].rmaxs + Tree[R(x)].lmaxs);
        Tree[x].minsum = min(min(Tree[L(x)].minsum, Tree[R(x)].minsum), Tree[L(x)].rmins + Tree[R(x)].lmins);
        Tree[x].min = min(Tree[L(x)].min, Tree[R(x)].min);
        Tree[x].max = max(Tree[L(x)].max, Tree[R(x)].max); 
        
} 

void build(int l, int r, int x)
 {
        Tree[x].l = l;
        Tree[x].r = r;
        if (l == r)
        {
               Tree[x].maxsum = Tree[x].minsum = Tree[x].sum = array[l];
               Tree[x].lmaxs = Tree[x].rmaxs = Tree[x].sum;
               Tree[x].lmins = Tree[x].rmins = Tree[x].sum;
               Tree[x].max = Tree[x].min = Tree[x].sum; 
               return; 
        } 
        int mid = (l + r) /2;
        build(l, mid, L(x));
        build(mid + 1, r, R(x));
        update_sum(x); 
        
}


 void update(int nu, int val, int x)
{
       if (Tree[x].l == Tree[x].r)
       {
               if (Tree[x].sum >= 0 && val < 0)poscnt--, negcnt++;
               else if (Tree[x].sum < 0 && val >= 0)poscnt++, negcnt--; 
               Tree[x].maxsum = Tree[x].minsum = Tree[x].sum = val;
               Tree[x].lmaxs = Tree[x].rmaxs = Tree[x].sum;
               Tree[x].lmins = Tree[x].rmins = Tree[x].sum;
               Tree[x].max = Tree[x].min = Tree[x].sum; 
               return;
       }
       int mid = (Tree[x].l + Tree[x].r) /2;
       if (nu <= mid)
       {
              update(nu, val, L(x));
              update_sum(L(x));
       }
       else
       {
              update(nu, val, R(x));
              update_sum(R(x));
       }
       update_sum(x); 
} 

int main()
{
      // FILE* fp = fopen("in.txt", "r");
       int n, m; 
       scanf(  "%d", &n);
       poscnt = negcnt = 0; 
       for (int i = 1; i <= n; i++)
       { 
            scanf( "%d", array + i);
            if (array[i] < 0)negcnt++;
            else poscnt++;
       } 
       scanf( "%d", &m); 
       build(1, n, 1); 
       int a, b; 
       while (m--)
       {
             scanf( "%d %d", &a, &b);
             update(a, b, 1);
             int ans; 
              if (poscnt == n)ans = Tree[1].sum - Tree[1].min;
              else if (poscnt == 0)ans = Tree[1].max; 
              else
              {
                    ans = max(Tree[1].maxsum, Tree[1].sum - Tree[1].minsum);
              } 
              
              printf("%d\n", ans);
       }
       //getchar();
       return 0;
} 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值