poj 2750 Potted Flower(线段树+DP)

题目:http://poj.org/problem?id=2750

题意:n个节点的环,在这个环中找到最大的连续字段和,,。。。

思路:建立一个线段树,每个节点有7个值,

          sum这一段的总和;

          lmin,lmax从左向右和最小、最大;

          rmin,rmax从右向左和最小、最大;

          amin,amax这一段的和最小、最大;

    节点的更新为:push函数

    

 1 void push(int w)//节点的更新
 2 {
 3     tree[w].sum=tree[L].sum+tree[R].sum;
 4     tree[w].lmin=min(tree[L].lmin,tree[L].sum+tree[R].lmin);
 5     tree[w].lmax=max(tree[L].lmax,tree[L].sum+tree[R].lmax);
 6 
 7     tree[w].rmin=min(tree[R].rmin,tree[R].sum+tree[L].rmin);
 8     tree[w].rmax=max(tree[R].rmax,tree[R].sum+tree[L].rmax);
 9 
10     tree[w].amin=min(min(tree[L].amin,tree[R].amin),tree[L].rmin+tree[R].lmin);
11     tree[w].amax=max(max(tree[L].amax,tree[R].amax),tree[L].rmax+tree[R].lmax);
12 }
View Code

 

注意:当n个数全为非负时,只能选n-1个;

   因为是环,用所有数的和减去最小与最大值比较,找出大的就是所求值;

代码:

  1 #include <iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #define L w<<1
  6 #define R w<<1|1
  7 using namespace std;
  8 const int maxn=100100;
  9 
 10 struct node
 11 {
 12     int lmin,lmax;
 13     int rmin,rmax;
 14     int sum;
 15     int amin,amax;
 16 }tree[maxn*4];
 17 int map[maxn],p;
 18 int max(int a,int b)
 19 {
 20     if(a>b)
 21     return a;
 22     else
 23     return b;
 24 }
 25 int min(int a,int b)
 26 {
 27     if(a<b)
 28     return a;
 29     else
 30     return b;
 31 }
 32 void push(int w)//节点的更新
 33 {
 34     tree[w].sum=tree[L].sum+tree[R].sum;
 35     tree[w].lmin=min(tree[L].lmin,tree[L].sum+tree[R].lmin);
 36     tree[w].lmax=max(tree[L].lmax,tree[L].sum+tree[R].lmax);
 37 
 38     tree[w].rmin=min(tree[R].rmin,tree[R].sum+tree[L].rmin);
 39     tree[w].rmax=max(tree[R].rmax,tree[R].sum+tree[L].rmax);
 40 
 41     tree[w].amin=min(min(tree[L].amin,tree[R].amin),tree[L].rmin+tree[R].lmin);
 42     tree[w].amax=max(max(tree[L].amax,tree[R].amax),tree[L].rmax+tree[R].lmax);
 43 }
 44 void build(int l,int r,int w)
 45 {
 46     if(l==r)
 47     {
 48         int u;
 49         scanf("%d",&u);
 50         tree[w].sum=u;
 51         tree[w].lmin=tree[w].lmax=tree[w].rmin=tree[w].rmax=u;
 52         tree[w].amin=tree[w].amax=u;
 53         return ;
 54     }
 55     int m=(l+r)>>1;
 56     build(l,m,L);
 57     build(m+1,r,R);
 58     push(w);
 59 }
 60 void update(int pos,int nnew,int l,int r,int w)
 61 {
 62     if(l==r)
 63     {
 64         tree[w].sum=nnew;
 65         tree[w].lmin=tree[w].lmax=tree[w].rmin=tree[w].rmax=nnew;
 66         tree[w].amin=tree[w].amax=nnew;
 67         return ;
 68     }
 69     int m=(l+r)>>1;
 70     if(pos<=m)
 71     update(pos,nnew,l,m,L);
 72     else
 73     update(pos,nnew,m+1,r,R);
 74     push(w);
 75 }
 76 int main()
 77 {
 78     int n;
 79     while(scanf("%d",&n)!=EOF)
 80     {
 81         int i;
 82         p=1;
 83         build(1,n,1);
 84         int Q;
 85         int a,b;
 86         scanf("%d",&Q);
 87         for(i=0;i<Q;i++)
 88         {
 89             scanf("%d%d",&a,&b);
 90             update(a,b,1,n,1);
 91             int res;
 92             if(tree[1].sum==tree[1].amax)//全为非负数的情况
 93             res=tree[1].sum-tree[1].amin;
 94             else
 95             res=max(tree[1].amax,tree[1].sum-tree[1].amin);//因为是环
 96             printf("%d\n",res);
 97         }
 98     }
 99     return 0;
100 }
View Code

 

posted @ 2013-06-18 21:50  琳&leen  阅读(290)  评论(0编辑  收藏  举报