做题记录整理线段树2 P4513. 小白逛公园(2022/9/20)

P4513. 小白逛公园

我们思考一个如何使用线段树维护这个答案,会发现

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;
}


posted @ 2022-09-20 15:13  yyx525jia  阅读(21)  评论(0)    收藏  举报