我们思考一个如何使用线段树维护这个答案,会发现
l.r的答案=max(l,mid的答案,mid+1,r的答案,横跨两个区间的答案)
那么我们现在再引入一个区间的最大前缀和最大后缀,这题就变成了
l.r的答案=max(l,mid的答案,mid+1,r的答案,l,mid的最大后缀+mid+1,r的最大前缀)
此时我们就变成了思考如何维护最大前缀,和最大后缀,显而易见
l.r的最大前缀=max(l,mid的最大前缀,l,mid的和+mid+1,r的最大前缀)
最大后缀同理,所以我们有引入了了一个区间求和,一起处理就得了
#include<bits/stdc++.h>
using namespace std;
#define for1(i,a,b) for(ll i = a;i <=b;i++)
#define ll long long
ll n,a[600000],m,x,y,k,ji;
struct node {
ll l;
ll r;
ll zhi;
ll mxl;
ll mxr;
ll ans;
} s[600000*4];
void pushup(ll q) {
s[q].zhi=s[q*2].zhi+s[q*2+1].zhi;
s[q].mxl=max(s[q*2].mxl,s[q*2].zhi+s[q*2+1].mxl);
s[q].mxr=max(s[q*2+1].mxr,s[q*2+1].zhi+s[q*2].mxr);
s[q].ans=max(max(s[q*2].ans,s[q*2+1].ans),s[q*2].mxr+s[q*2+1].mxl);
return ;
}
void build(ll q,ll l,ll r) {
s[q].l=l;
s[q].r=r;
if(l==r) {
s[q].zhi=a[l];
s[q].mxl=a[l];
s[q].mxr=a[l];
s[q].ans=a[l];
return ;
}
ll mid = (l+r)/2;
build(q*2,l,mid);
build(q*2+1,mid+1,r);
pushup(q);
}
void xg(ll q,ll l,ll k)
{
ll mid = (s[q].l+s[q].r)/2;
if(s[q].l==l&&s[q].r==l) {
s[q].zhi=k;
s[q].mxr=k;
s[q].mxl=k;
s[q].ans=k;
return ;
}
if(l<=mid) xg(q*2,l,k);
if(l>mid) xg(q*2+1,l,k);
pushup(q);
}
ll qhz(ll q,ll l,ll r)//zhi
{
ll mid = (s[q].l+s[q].r)/2;
if(s[q].l>=l&&s[q].r<=r) {
return s[q].zhi;
}
ll ans=0;
if(l<=mid) ans+=qhz(q*2,l,r);
if(r>mid) ans+=qhz(q*2+1,l,r);
return ans;
}
ll qh2(ll q,ll l,ll r)//mxl
{
ll mid = (s[q].l+s[q].r)/2;
if(s[q].l>=l&&s[q].r<=r) {
return s[q].mxl;
}
ll ans=-1e8;
ll zmxl=-1e8;;
ll ymxl=-1e8;
ll zzhi=-1e8;
if(l<=mid) zmxl=qh2(q*2,l,r),zzhi=qhz(q*2,l,r);
if(r>mid) ymxl=qh2(q*2+1,l,r);
ans=max(zmxl,zzhi+ymxl);
return ans;
}
ll qh3(ll q,ll l,ll r)//mxr
{
ll mid = (s[q].l+s[q].r)/2;
if(s[q].l>=l&&s[q].r<=r) {
return s[q].mxr;
}
ll ans=-1e8;
ll zmxr=-1e8;;
ll ymxr=-1e8;
ll yzhi=-1e8;
if(l<=mid) zmxr=qh3(q*2,l,r);
if(r>mid) ymxr=qh3(q*2+1,l,r),yzhi=qhz(q*2+1,l,r);
ans=max(ymxr,yzhi+zmxr);
return ans;
}
ll qh(ll q,ll l,ll r)//ans
{
ll mid = (s[q].l+s[q].r)/2;
if(s[q].l>=l&&s[q].r<=r) {
return s[q].ans;
}
ll ans=0;
ll zans=-1e8;
ll yans=-1e8;
ll zmxr=-1e8;
ll ymxl=-1e8;
if(l<=mid) yans=qh(q*2,l,r),zmxr=qh3(q*2,l,r);
if(r>mid) zans=qh(q*2+1,l,r),ymxl=qh2(q*2+1,l,r);
ans=max(zans,max(yans,zmxr+ymxl));
return ans;
}
int main() {
scanf("%lld%lld",&n,&m);
for1(i,1,n)scanf("%lld",&a[i]);
build(1,1,n);
for1(i,1,m) {
scanf("%lld",&ji);
if(ji==2) {
scanf("%lld%lld",&x,&k);
xg(1,x,k);
} else {
scanf("%lld%lld",&x,&y);
if(x>y) swap(x,y);
printf("%lld\n",qh(1,x,y));
}
}
return 0;
}
标签:20,前缀,max,ll,mid,2022,ans,P4513,lld
From: https://www.cnblogs.com/yyx525jia/p/16711110.html