POJ 2750 Potted Flower 线段树区间合并

题目大意:一个圆环上有n(4<= n <= 100000)个数字,编号依次从1到n,第n个数与第1个数相连。规则是:从环上选取任意个数(但不能为0也不能取全部)的连续数字,使选取数字之和最大。但现在有m(4<= m <= 100000)个操作,用a, b两个数字来描述, 意思是:将环上编号为a的数字换成b。现要求每次操作后都按照规则输出最大之和。更多细节点击传送门

思路:因为查询次数太大,用线段树来维护数据。将圆环从编号为1和n的数字间断开,扯成直线。因不能选择全部数字的限制,将情况分成两种。

1. 圆环上的数全是正数。所有数字之和减去其中最小的一个数,即为结果。

2. 圆环上的数有负数。此时有两种选取数字的方式:

  1. 所选的连续数字包含编号1和n的两个数。此时在线段树内他们并不连续(在1和n之间被断开了)。所有数字之和减去线段树区间内数字最小之和即为结果。

  2. 所选的连续数字不包含1和n两个数。用线段树维护出区间内最大连续数字之和即可。

线段树需要维护7个数据:sum, lmax, rmax, tmax, lmin, rmin, tmin。

其中lmax意为从区间左端第一个数开始的最大连续数字之和,rmax意为从区间右端第一个数开始的最大连续数字之和,tmax意为整个区间的最大连续数字之和。 min同理。

至于条件判定,当圆环上全是正数时,对于整个区间有sum=tmax。

各区间合并的具体公式见代码中PushUp函数。

 1 #include<stdio.h>

 2 #include<algorithm>

 3 #define maxn 100010

 4 #define lson l, m, rt << 1

 5 #define rson m + 1, r, rt << 1 | 1

 6 using namespace std;

 7 int sum[maxn<<2], lmax[maxn<<2], rmax[maxn<<2], tmax[maxn<<2];

 8 int lmin[maxn<<2], rmin[maxn<<2], tmin[maxn<<2];

 9 void PushUp(int rt)

10 {

11     sum[rt] = sum[rt<<1] + sum[rt<<1|1];

12     lmax[rt] = max(lmax[rt<<1], sum[rt<<1] + lmax[rt<<1|1]);

13     rmax[rt] = max(rmax[rt<<1|1], sum[rt<<1|1] + rmax[rt<<1]);

14     tmax[rt] = max(tmax[rt<<1], max(tmax[rt<<1|1], rmax[rt<<1] + lmax[rt<<1|1]));

15     lmin[rt] = min(lmin[rt<<1], sum[rt<<1] + lmin[rt<<1|1]);

16     rmin[rt] = min(rmin[rt<<1|1], sum[rt<<1|1] + rmin[rt<<1]);

17     tmin[rt] = min(min(tmin[rt<<1], tmin[rt<<1|1]), rmin[rt<<1] + lmin[rt<<1|1]);

18 }

19 void build(int l,int r,int rt)

20 {

21     if (l == r)

22     {

23         scanf("%d",&sum[rt]);

24         lmax[rt] = rmax[rt] = tmax[rt] = lmin[rt] = rmin[rt] = tmin[rt] = sum[rt];

25         return;

26     }

27     int m = (l + r) >> 1;

28     build(lson);

29     build(rson);

30     PushUp(rt);

31 }

32 void update(int a,int b,int l,int r,int rt)

33 {

34     if (l == r && l == a)

35     {

36         lmax[rt] = rmax[rt] = tmax[rt] = lmin[rt] = rmin[rt] = tmin[rt] = sum[rt] = b;

37         return;

38     }

39     int m = (l + r) >> 1;

40     if (a <= m) update(a, b, lson);

41     else update(a, b, rson);

42     PushUp(rt);

43 }

44 int main()

45 {

46     int n, m;

47     //freopen("data.in","r",stdin);

48     scanf("%d",&n);

49     build(1, n, 1);

50     scanf("%d",&m);

51     while (m--)

52     {

53         int a, b;

54         scanf("%d%d",&a,&b);

55         update(a, b, 1, n, 1);

56         if (sum[1] == tmax[1]) printf("%d\n",sum[1] - tmin[1]);

57         else printf("%d\n",max(tmax[1], sum[1] - tmin[1]));

58     }

59     return 0;

60 }

 

你可能感兴趣的:(poj)