CODEVS 3981(求最大子段和+线段树)

Posted lllaih

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CODEVS 3981(求最大子段和+线段树)相关的知识,希望对你有一定的参考价值。

题目链接:http://codevs.cn/problem/3981/

参考:https://blog.csdn.net/jokingcoder/article/details/81477253

一个区间的最大子段和有三种情况:

1.等于这个区间左儿子的最大子段和

2.等于这个区间右儿子的最大子段和

3.等于这个区间左儿子的后缀最大子段和+右儿子的前缀最大子段和

    tree[k].sumax = max(max(tree[l].sumax,tree[r].sumax),tree[l].rmax + tree[r].lmax);

 

一个区间前缀最大子段和有两种情况:

1.等于这个区间左儿子的前缀最大子段和

2.等于这个这儿子的前缀和加上右儿子的前缀最大子段和

    tree[k].lmax = max(tree[l].lmax,tree[l].sum + tree[r].lmax);

 

同样

一个区间的后缀最大子段和有两种情况:

1.等于这个区间右儿子的后缀最大子段和

2.等于这个区间右儿子的后缀和+左儿子的最大后缀和

    tree[k].rmax = max(tree[r].rmax,tree[r].sum + tree[l].rmax);

 

 1 #include <iostream>
 2 #include <cstring>
 3 #define mem(a,b) memset(a,b,sizeof(a));
 4 using namespace std;
 5 typedef long long ll;
 6 const int maxn = 500005;
 7 const ll INF = 0x3f3f3f3f;
 8 ll n,q,a[maxn];
 9 struct node
10     ll sum,sumax,lmax,rmax;
11 tree[maxn];
12 void pushup(ll k) 
13     ll l = k << 1, r = k << 1 | 1;
14     tree[k].sum = tree[l].sum + tree[r].sum;
15     tree[k].sumax = max(max(tree[l].sumax,tree[r].sumax),tree[l].rmax + tree[r].lmax);
16     tree[k].lmax = max(tree[l].lmax,tree[l].sum + tree[r].lmax);
17     tree[k].rmax = max(tree[r].rmax,tree[r].sum + tree[l].rmax);
18 
19 void build(ll k,ll l,ll r) 
20     if(l == r) 
21         tree[k].lmax = tree[k].rmax = tree[k].sum = tree[k].sumax = a[l];
22         return ;
23     
24     ll mid = (l + r) >> 1;
25     build(k << 1, l, mid);
26     build(k << 1 | 1,mid + 1, r);
27     pushup(k);
28 
29 node Search(ll l,ll r,ll L,ll R,ll k) 
30     if(L <= l&& R >= r) 
31         return tree[k];
32     
33     ll mid = (l + r) >> 1,ld = k << 1, rd = k << 1 | 1;
34     if(R <= mid) return Search(l,mid,L,R,ld);
35     if(L > mid) return Search(mid+1,r,L,R,rd);
36     node lo = Search(l,mid,L,R,ld), ro = Search(mid+1,r,L,R,rd),ans;
37     ans.sum = lo.sum + ro.sum;
38     ans.sumax = max(max(lo.sumax,ro.sumax),lo.rmax+ro.lmax);
39     ans.lmax = max(lo.lmax,lo.sum+ro.lmax);
40     ans.rmax = max(ro.rmax,ro.sum+lo.rmax);
41     return ans;
42 
43 int main()
44 
45     cin >> n;
46     for(ll i = 1; i <= n; i++) 
47         cin >> a[i];
48     
49     build(1,1,n);
50     cin >> q;
51     ll x,y;
52     for(ll i = 1; i <= q; i++) 
53         cin >> x >> y;
54         cout << Search(1,n,x,y,1).sumax << endl;
55     
56     return 0;
57 

 

以上是关于CODEVS 3981(求最大子段和+线段树)的主要内容,如果未能解决你的问题,请参考以下文章

codevs 3981 动态最大子段和

线段树复习

3981 动态最大子段和

HDU6638 Snowy Smile (线段树+二维最大子段和)

[题解](线段树最大连续子段和)POJ_3667_Hotel

线段树维护区间最大子段和