题解 【SR2.7-T2】【文文的摄影布置】
题目大意
给定两个长度均为
n 的数组A_i 和B_i 。有m 次操作,每次操作将A_x 修改为y 或者将B_x 修改为y 或者求出\max_{x\le i<j\le y} \{A_i+A_j-\min_{i < k < j}(B_k)\}
题解
在下文中,不妨记一段区间
那么对于每次询问,问题转化为了计算
非常自然的想法是,每个节点都要维护它所代表的这段区间的最优解。也就是说,假如一个节点
-
首先考虑最优的
a,b,c 在同一个儿子中的情况。显然,这样对答案的更新就是\max\{\Psi(\alpha),\Psi(\beta)\} 。 -
然后考虑
a 在\alpha 中,而c 在\beta 中的情况。考虑第二张照片在哪。可以发现,假如第二张照片在\alpha 中,那么c 的最优解必定是\beta 中A 的值最大的那个元素。同理,假如第二张照片在\beta 中,那么a 的最优解必定是\alpha 中A 的值最大的那个元素。而维护 每个节点对应区间上的\max \{A_i\} 是相当容易的。于是,问题转化为了在一个节点维护的区间中,这样的两个值:
\max_{l\le a<b\le r}\{A_a-B_b\} \max_{l\le b<c\le r}\{A_c-B_b\} 不妨分别记为
P(\omega) 和Q(\omega) 。考虑怎么从它的左右儿子上转移过来。对于
P(\omega) ,其最优的a,b 又可以分为如下三类:P(\omega)=\max\{P(\alpha),P(\beta),X(\alpha)-Y(\beta)\} 同理,我们可以得到
Q(\omega) 的维护方法。 -
最终,我们能得到所有东西的转移方程式:
对于查询操作,我们只要把涉及到的区间从左往右一个一个合并起来,再查询它的
参考代码
#include<bits/stdc++.h>
#define up(l,r,i) for(int i=l,END##i=r;i<=END##i;++i)
#define dn(r,l,i) for(int i=r,END##i=l;i>=END##i;--i)
using namespace std;
typedef long long i64;
const int INF =5e8,MAXN=5e5+3,SIZ=MAXN*4;
int A[MAXN],B[MAXN];
#define lc(t) (t<<1)
#define rc(t) (t<<1|1)
struct Node{
int a,b,p,q,w; Node():a(-INF),b(INF),p(-INF),q(-INF),w(-INF){}
Node operator +(Node t){
Node r; r.a=max(a,t.a),r.b=min(b,t.b),r.w=max(w,t.w);
r.p=max(t.p,max(p,a-t.b)),r.q=max(q,max(t.q,t.a-b));
r.w=max(r.w,max(p+t.a,a+t.q)); return r;
}
}W[SIZ];
void sst(int t,int l,int r,int p){
if(l==r) W[t].a=A[l],W[t].b=B[l]; else {
int c=l+r>>1; p<=c?sst(lc(t),l,c,p):sst(rc(t),c+1,r,p);
W[t]=W[lc(t)]+W[rc(t)];
}
}
void qry(int t,int l,int r,int a,int b,Node &o){
if(a<=l&&r<=b) o=o+W[t]; else {
int c=l+r>>1;
if(a<=c) qry(lc(t),l ,c,a,b,o);
if(b> c) qry(rc(t),c+1,r,a,b,o);
}
}
void bld(int t,int l,int r){
if(l==r){W[t].a=A[l],W[t].b=B[l]; return;}
int c=l+r>>1; bld(lc(t),l,c),bld(rc(t),c+1,r);
W[t]=W[lc(t)]+W[rc(t)];
}
int n,q,m,p;
int qread(){
int w=1,c,ret;
while((c=getchar())> '9'||c< '0') w=(c=='-'?-1:1); ret=c-'0';
while((c=getchar())>='0'&&c<='9') ret=ret*10+c-'0';
return ret*w;
}
int main(){
n=qread(),m=qread(); up(1,n,i) A[i]=qread(); up(1,n,i) B[i]=qread();
bld(1,1,n); up(1,m,i){
int op=qread(),x=qread(),y=qread(); Node r; switch(op){
case 1: A[x]=y,sst(1,1,n,x); break;
case 2: B[x]=y,sst(1,1,n,x); break;
case 3: qry(1,1,n,x,y,r),printf("%d\n",r.w);
}
}
return 0;
}