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 }

 

你可能感兴趣的:(poj)