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这个序列不包含最大子序列和,那么它肯定包含最小子序列和。
换个角度想问题,从方面思考。
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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) 编辑 收藏 举报