RT,具体思路跟题解一样,查询的时候有点变化。具体看代码注释。谢谢各位神仙
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
using namespace std;
const ll INF=1e14;
const int N=5e5+10;
int n,m;
ll maxa,maxsuf;
int tp;
ll st[N];
struct
{
int l,r;
ll maxa,minb,phi,pre,suf;//pre表示这个节点所代表的区间的最大的a-b,其中a在b后面
//同理suf代表a在b前面的最大的值
//phi表示这个区间的答案
}t[N<<3];
ll a[N],b[N];
int read()
{
int x=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-f;s=getchar();}
while(s>='0'&&s<='9'){x=x*10+s-48;s=getchar();}
return x*f;
}
void build(int p,int l,int r)
{
t[p].l=l,t[p].r=r;
if(l==r)
{
t[p].maxa=a[l];
t[p].minb=b[l];
t[p].suf=t[p].phi=t[p].pre=-INF;
return;
}
int mid=l+r>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
t[p].maxa=max(t[p<<1].maxa,t[p<<1|1].maxa);
t[p].minb=min(t[p<<1].minb,t[p<<1|1].minb);
t[p].pre=max(t[p<<1|1].maxa-t[p<<1].minb,max(t[p<<1].pre,t[p<<1|1].pre));
t[p].suf=max(t[p<<1].maxa-t[p<<1|1].minb,max(t[p<<1].suf,t[p<<1|1].suf))
t[p].phi=max(t[p<<1].suf+t[p<<1|1].maxa,max(t[p<<1|1].pre+t[p<<1].maxa,max(t[p<<1].phi,t[p<<1|1].phi)));
}
ll ask(int p,int l,int r)//这个函数查询每个区间的最大答案值
{
if(t[p].l>r||t[p].r<l) return -INF;
if(t[p].l>=l&&t[p].r<=r) return t[p].phi;
return max(ask(p<<1,l,r),ask(p<<1|1,l,r));
}
ll ask1(int p,int l,int r)//这个函数假设需要知道一个区间的pre,另一个a(即三元组的最开始的a在前面已经查询过的区间),然后更新最大值;而同时讨论suf的情况
{
if(t[p].l>r||t[p].r<l) return -INF;
if(t[p].l>=l&&t[p].r<=r)
{
ll Max=max(t[p].pre+maxa,maxsuf+t[p].maxa);
maxa=max(maxa,t[p].maxa);
maxsuf=max(maxsuf,t[p].suf);
return Max;
}
ll Max=ask1(p<<1,l,r);
Max=max(Max,ask1(p<<1|1,l,r));
return Max;
}
ll ask2(int p,int l,int r)//这个函数表示三元组的每一个元素都不在同一个区间,我们需要知道当前节点的minb,前面所查询过得区间的最大值a,以及后面还没有查询的区间的最大值a,用三者更新答案
{
if(t[p].l>r||t[p].r<l) return -INF;
if(t[p].l>=l&&t[p].r<=r)
{
tp--;
ll Max=maxa+st[tp]-t[p].minb;
maxa=max(maxa,t[p].maxa);
return Max;
}
ll Max=ask2(p<<1,l,r);
Max=max(Max,ask2(p<<1|1,l,r));
return Max;
}
void search(int p,int l,int r)//这个函数用来维护当前询问后面未走过的区间的最大值a,类似于“对顶堆”
{
if(t[p].l>r||t[p].r<l) return;
if(t[p].l>=l&&t[p].r<=r)
{
st[++tp]=max(t[p].maxa,st[tp-1]);
return;
}
search(p<<1|1,l,r);
search(p<<1,l,r);
}
void modify(int p,int x,ll y,int op)
{
if(t[p].l>x||t[p].r<x) return;
if(t[p].l==t[p].r)
{
if(op==1) t[p].maxa=y;
else t[p].minb=y;
return;
}
modify(p<<1,x,y,op);
modify(p<<1|1,x,y,op);
t[p].maxa=max(t[p<<1].maxa,t[p<<1|1].maxa);
t[p].minb=min(t[p<<1].minb,t[p<<1|1].minb);
t[p].pre=max(t[p<<1|1].maxa-t[p<<1].minb,max(t[p<<1].pre,t[p<<1|1].pre));
t[p].suf=max(t[p<<1].maxa-t[p<<1|1].minb,max(t[p<<1].suf,t[p<<1|1].suf));
t[p].phi=max(t[p<<1].suf+t[p<<1|1].maxa,max(t[p<<1|1].pre+t[p<<1].maxa,max(t[p<<1].phi,t[p<<1|1].phi)));
}
int main()
{
n=read(),m=read();
for(int i=1;i<=n;i++)
a[i]=read();
for(int i=1;i<=n;i++)
b[i]=read();
build(1,1,n);
st[0]=-INF;
for(int i=1,op,x,y;i<=m;i++)
{
op=read(),x=read(),y=read();
if(op==3)
{
tp=0;
search(1,x,y);
maxa=maxsuf=-INF;
ll ans=max(ask(1,x,y),ask1(1,x,y));
maxa=-INF;
ans=max(ans,ask2(1,x,y));
printf("%lld\n",ans);
}
else modify(1,x,(ll)y,op);
}
return 0;
}