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(求最大子段和+线段树)的主要内容,如果未能解决你的问题,请参考以下文章
HDU6638 Snowy Smile (线段树+二维最大子段和)