【线段树维护最大子段和】洛谷 P4513 小白逛公园
2021-03-16 13:34:00 # ACM

题链

题意求区间最长连续子序列最大和

当数据存在负数时,不能单纯取三个地方的$max$,如:

1
p[rt].maxn = max(p[ls].rmax+p[rs].lmax,max(p[rt].lmax,p[rt].rmax));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include <bits/stdc++.h>
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//#pragma GCC optimize("O2")
using namespace std;
#define LL long long
#define ll long long
#define ULL unsigned long long
#define ls rt<<1
#define rs rt<<1|1
#define one first
#define two second
#define MS 500009
#define INF 1e18
#define mod 99999997
#define Pi acos(-1.0)
#define Pair pair<LL,LL>
#define eps 1e-9

LL n,m,k;
struct node{
LL sum;
LL lmax,rmax;
LL maxn;
}p[MS<<2];

void push_up(int rt){
p[rt].sum = p[ls].sum + p[rs].sum;
p[rt].lmax = max(p[ls].lmax,p[ls].sum+p[rs].lmax);
p[rt].rmax = max(p[rs].rmax,p[rs].sum+p[ls].rmax);

//p[rt].maxn = max(p[ls].rmax+p[rs].lmax,max(p[rt].lmax,p[rt].rmax)); // 当数据存在负数时,该条不成立

/**************************************************/ // 将所有可能对maxn产生影响的都取最大
LL sidemax = max(p[rt].lmax,p[rt].rmax);
LL midmax = max(p[ls].rmax,p[rs].lmax);
LL lrmaxn = max(p[ls].maxn,p[rs].maxn);
p[rt].maxn = max(sidemax,midmax);
p[rt].maxn = max(p[rt].maxn,lrmaxn);
p[rt].maxn = max(p[rt].maxn,p[ls].rmax+p[rs].lmax);
/**************************************************/
}

void build(int l,int r,int rt){
if(l == r){
LL x;
cin >> x;
p[rt] = {x,x,x,x};
return;
}
int m = l+r>>1;
build(l,m,ls);
build(m+1,r,rs);
push_up(rt);
}

void update(int L,int R,int l,int r,int rt,LL val){
if(L <= l && r <= R){
p[rt] = {val,val,val,val};
return;
}
int m = l+r>>1;
if(m >= L) update(L,R,l,m,ls,val);
if(m < R) update(L,R,m+1,r,rs,val);
push_up(rt);
}

node get_max(int L,int R,int l,int r,int rt){
if(L <= l && r <= R){
return p[rt];
}
int m = l+r>>1;
node ans;
if(L <= m && m < R){
node t1 = get_max(L,R,l,m,ls);
node t2 = get_max(L,R,m+1,r,rs);
ans.lmax = max(t1.lmax,t1.sum+t2.lmax);
ans.rmax = max(t2.rmax,t2.sum+t1.rmax);
ans.sum = t1.sum + t2.sum;
/**************************************************/ // 将所有可能对maxn产生影响的都取最大
LL sidemax = max(ans.lmax,ans.rmax);
LL midmax = max(t1.rmax,t2.lmax);
LL lrmax = max(t1.maxn,t2.maxn);
ans.maxn = max(sidemax,midmax);
ans.maxn = max(ans.maxn,lrmax);
ans.maxn = max(ans.maxn,t1.rmax+t2.lmax);
/**************************************************/
return ans;
}
else if(m < L) return get_max(L,R,m+1,r,rs);
else return get_max(L,R,l,m,ls);
}

int main(){
ios::sync_with_stdio(false);
cin >> n >> m;
build(1,n,1);
while(m--){
LL op,l,r,pos,tar;
cin >> op;
if(op == 1){
cin >> l >> r;
if(l > r) swap(l,r); // 不交换则会在 TLE 之前就会出现 MLE
node cc = get_max(l,r,1,n,1);
cout << cc.maxn << endl;
}
else{
cin >> pos >> tar;
update(pos,pos,1,n,1,tar);
}
}



return 0;
}
Prev
2021-03-16 13:34:00 # ACM
Next