分析
这道题属于考察对于合并时不同最佳状态的讨论,我们考虑最后选出来的那三张照片位置在哪里,发现有四种情况(中间隔开处为线段树区间的 \(mid\))。
1、\(ijk\)|。
2、|\(ijk\)。
3、\(ij\)|\(k\)。
4、\(i\)|\(jk\)。
显然前两种情况就是子节点的答案,而后两种情况需要用到以下值:最大 \(a\) 值,最大的 \(a_i-b_j(i<j)\),最大的 \(a_i-b_j(i>j)\)。而后两个值又要用到最小 \(b\) 值,所以最终我们一共维护五个值即可。
代码
#include<bits/stdc++.h>
using namespace std;
#define ls rt<<1
#define rs rt<<1|1
inline void read(int &res){
res=0;
int f=1;
char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9')res=(res<<1)+(res<<3)+c-48,c=getchar();
res*=f;
}
int n,m;
struct node{
int mxa,mnb,ml,mr,as;
}a[2000005];
void pushup(node &x,node y,node z){
x.mxa=max(y.mxa,z.mxa);
x.mnb=min(y.mnb,z.mnb);
x.ml=max(y.ml,max(z.ml,y.mxa-z.mnb));//最大的 a[i]-b[j](i<j)
x.mr=max(z.mr,max(y.mr,z.mxa-y.mnb));//最大的 a[i]-b[j](i>j)
x.as=max(y.as,max(z.as,max(y.ml+z.mxa,z.mr+y.mxa)));//答案,取四种情况最大值
}
int csa[500005],csb[500005];
void build(int rt,int l,int r){
if(l==r){
a[rt].mxa=csa[l];
a[rt].mnb=csb[l];
a[rt].ml=a[rt].mr=a[rt].as=-1e9;//这个初值一定要赋,负答案是可能出现的
return;
}
int mid=(l+r)>>1;
build(ls,l,mid);
build(rs,mid+1,r);
pushup(a[rt],a[ls],a[rs]);
}
void modifya(int rt,int l,int r,int L,int k){
if(l==r){
a[rt].mxa=k;
return;
}
int mid=(l+r)>>1;
if(mid>=L)modifya(ls,l,mid,L,k);
else modifya(rs,mid+1,r,L,k);
pushup(a[rt],a[ls],a[rs]);
}
void modifyb(int rt,int l,int r,int L,int k){
if(l==r){
a[rt].mnb=k;
return;
}
int mid=(l+r)>>1;
if(mid>=L)modifyb(ls,l,mid,L,k);
else modifyb(rs,mid+1,r,L,k);
pushup(a[rt],a[ls],a[rs]);
}
node query(int rt,int l,int r,int L,int R){
if(l>=L&&R>=r)return a[rt];
int mid=(l+r)>>1;
if(mid>=R)return query(ls,l,mid,L,R);
if(mid<L)return query(rs,mid+1,r,L,R);
node aa=query(ls,l,mid,L,R),bb=query(rs,mid+1,r,L,R),cc;
pushup(cc,aa,bb);
return cc;
}
int main()
{
read(n);read(m);
for(int i=1;i<=n;i++){
read(csa[i]);
}
for(int i=1;i<=n;i++){
read(csb[i]);
}
build(1,1,n);
while(m--){
int op,x,y;
read(op);read(x);read(y);
if(op==1){
modifya(1,1,n,x,y);
}
if(op==2){
modifyb(1,1,n,x,y);
}
if(op==3){
printf("%d\n",query(1,1,n,x,y).as);
}
}
}