码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2019-08-09 15:29:22      阅读:96      评论:0      收藏:0      [点我收藏+]

标签:memset   dev   前缀   pac   两种   前缀和   string   log   turn   

题目链接: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(求最大子段和+线段树)

标签:memset   dev   前缀   pac   两种   前缀和   string   log   turn   

原文地址:https://www.cnblogs.com/LLLAIH/p/11327225.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!