POJ 2750 Potted Flower(线段树+dp)

题目链接

虽然是看的别的人思路,但是做出来还是挺高兴的。

首先求环上最大字段和,而且不能是含有全部元素。本来我的想法是n个元素变为2*n个元素那样做的,这样并不好弄。实际可以求出最小值,总和-最小,就可以求出,断开的情况了。

然后线段树要单点更新,这种标记,以前遇到过,不过一直没有写过,注意总和好更新,整个这一段的结果也很好更新,最难想的就是左边 和右边标记的结果,具体看pushup代码。

 1 #include <cstring>
 2 #include <cstdio>
 3 #include <string>
 4 #include <iostream>
 5 #include <algorithm>
 6 #include <vector>
 7 #include <queue>
 8 using namespace std;
 9 #define maxn 100100
10 struct node
11 {
12     int sum,lmax,lmin,rmin,rmax;
13     int smax,smin;
14 }p[4*maxn];
15 void pushup(int rt)
16 {
17     p[rt].sum = p[rt<<1].sum + p[rt<<1|1].sum;
18     p[rt].smax = max(max(p[rt<<1].smax,p[rt<<1|1].smax),p[rt<<1].rmax+p[rt<<1|1].lmax);
19     p[rt].lmax = max(p[rt<<1].lmax,p[rt<<1].sum+p[rt<<1|1].lmax);
20     p[rt].rmax = max(p[rt<<1|1].rmax,p[rt<<1|1].sum+p[rt<<1].rmax);
21     p[rt].smin = min(min(p[rt<<1].smin,p[rt<<1|1].smin),p[rt<<1].rmin + p[rt<<1|1].lmin);
22     p[rt].lmin = min(p[rt<<1].lmin,p[rt<<1].sum+p[rt<<1|1].lmin);
23     p[rt].rmin = min(p[rt<<1|1].rmin,p[rt<<1|1].sum+p[rt<<1].rmin);
24 }
25 void build(int l,int r,int rt)
26 {
27     int m;
28     if(l == r)
29     {
30         scanf("%d",&p[rt].sum);
31         p[rt].lmax = p[rt].sum;
32         p[rt].rmax = p[rt].sum;
33         p[rt].smax = p[rt].sum;
34         p[rt].lmin = p[rt].sum;
35         p[rt].rmin = p[rt].sum;
36         p[rt].smin = p[rt].sum;
37         return ;
38     }
39     m = (l+r)>>1;
40     build(l,m,rt<<1);
41     build(m+1,r,rt<<1|1);
42     pushup(rt);
43 }
44 void update(int x,int sc,int l,int r,int rt)
45 {
46     int m;
47     if(l == x&&r == x)
48     {
49         p[rt].sum = sc;
50         p[rt].lmax = p[rt].sum;
51         p[rt].rmax = p[rt].sum;
52         p[rt].smax = p[rt].sum;
53         p[rt].lmin = p[rt].sum;
54         p[rt].rmin = p[rt].sum;
55         p[rt].smin = p[rt].sum;
56         return ;
57     }
58     m = (l+r)>>1;
59     if(x <= m)
60     update(x,sc,l,m,rt<<1);
61     if(x > m)
62     update(x,sc,m+1,r,rt<<1|1);
63     pushup(rt);
64 }
65 int main()
66 {
67     int n,m,i,a,b;
68     while(scanf("%d",&n)!=EOF)
69     {
70         build(1,n,1);
71         scanf("%d",&m);
72         for(i = 1;i <= m;i ++)
73         {
74             scanf("%d%d",&a,&b);
75             update(a,b,1,n,1);
76             if(p[1].sum == p[1].smax)//如果总和和最大值相同,断开一个最小值。
77             {
78                 printf("%d\n",p[1].sum - p[1].smin);
79             }
80             else
81             {
82                 printf("%d\n",max(p[1].smax,p[1].sum-p[1].smin));
83             }
84         }
85     }
86     return 0;
87 }

 

posted @ 2013-06-19 16:19  Naix_x  阅读(189)  评论(0编辑  收藏  举报