poj 2750 Potted Flower

看了解题报告才会做....

算法:

线段树 + 动态规划

线段树需要保存的信息:

struct node
{
int l,r; //左右端点
long long sum, max, min;//区间和,最大子序列和,最小子序列和
long long lmax, lmin, rmax, rmin;//左边连续最大和,左边连续子序列最小和,右边连续最大子序列和,右边连续最小子序列和
}seg[MAXN*4];

自己想时遇到的主要问题是,如何处理最大子序列和是首尾相连的这一序列。。。

不会处理这种问题。。。

看了别人解题报告才知道,只要保留一个最小子序列和就可以了,然后总和减去这个最小子序列和。。

如果1-N这个序列不包含最大子序列和,那么它肯定包含最小子序列和。

换个角度想问题,从方面思考。

代码:

View Code
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<iostream>
#include<vector>
#include<string>
#include<math.h>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
#define MAXN 1000000

struct node
{
 int l,r; //左右端点 
 long long sum, max, min;//区间和,最大子序列和,最小子序列和 
 long long lmax, lmin, rmax, rmin;//左边连续最大和,左边连续子序列最小和,右边连续最大子序列和,右边连续最小子序列和 
}seg[MAXN*4];

int val[300000];

void push( long long root )
{
   //更新区间和  
   seg[root].sum = seg[root << 1].sum + seg[(root << 1) + 1].sum;
   //求最大连续子序列和
   seg[root].max = max(max(seg[root << 1].max, seg[(root << 1) + 1].max), seg[root<<1].rmax + seg[(root<<1)+1].lmax);
   //求最小连续子序列和
   seg[root].min = min(min(seg[root << 1].min, seg[(root << 1) + 1].min), seg[root<<1].rmin + seg[(root<<1)+1].lmin);
   //更新Lmin,RMIN, lMAX, Rmax
   seg[root].lmax = max( seg[root << 1].lmax, seg[(root<<1)].sum + seg[(root<<1)+1].lmax );
   seg[root].rmax = max( seg[(root << 1)+1].rmax, seg[root << 1].rmax + seg[(root<<1) + 1].sum);
   seg[root].lmin =  min( seg[root << 1].lmin, seg[(root<<1)].sum + seg[(root<<1)+1].lmin );
   seg[root].rmin = min( seg[(root << 1)+1].rmin, seg[root << 1].rmin + seg[(root<<1) + 1].sum);
}

void build(int root, int l, int r)
{
  long long mid = (l + r) / 2;
  seg[root].l = l, seg[root].r = r;
  if( l == r )
  {  
     seg[root].lmax =  seg[root].rmax = seg[root].lmin = seg[root].rmin =  seg[root].sum = seg[root].max = seg[root].min = val[l];
     return;  
  }
  build(root << 1, l, mid);
  build((root << 1) + 1, mid + 1, r); 
  push(root);
}

void update(int root, int a, int b)
{
   int mid = (seg[root].l + seg[root].r ) / 2;
   if( seg[root].l == seg[root].r )
   {
       seg[root].lmax =  seg[root].rmax = seg[root].lmin = seg[root].rmin =  seg[root].sum = seg[root].max = seg[root].min = b;
       return;
   }
   if( mid >= a )
       update((root << 1), a, b);
   else
       update((root << 1) + 1, a, b);
   push(root);
}

int main( )
{
  int N, M, a, b;
  while( scanf("%d",&N) != EOF)
  {
     for( int i = 1; i <= N; i++)
          scanf("%d",&val[i]);
     scanf("%d",&M);
     build(1,1,N);
     for( int i = 1; i <= M; i++)
     {
        scanf("%d%d",&a,&b);
        update(1,a,b);     
        if( seg[1].max == seg[1].sum ) //此处Wa了N久 
        {
            printf("%lld\n", seg[1].sum - seg[1].min);
        }
        else
        printf("%lld\n", max(seg[1].max,seg[1].sum - seg[1].min));
     }       
  }
  return 0;
}

posted on 2012-09-17 19:31  more think, more gains  阅读(196)  评论(0编辑  收藏  举报

导航