题意:
给出两个长度为
N
N
N的整数序列
A
1
A
2
.
.
.
A
N
A_1A_2...A_N
A1A2...AN,
B
1
B
2
.
.
.
B
N
B_1B_2...B_N
B1B2...BN。有
M
M
M组询问
(
o
p
t
,
l
,
r
,
d
)
(opt,l,r,d)
(opt,l,r,d),令
n
=
r
−
l
+
1
n=r-l+1
n=r−l+1
若
o
p
t
=
A
opt=A
opt=A:
∀
i
∈
[
1
,
n
]
,
a
i
=
A
l
+
i
−
1
+
d
,
b
i
=
B
l
+
i
−
1
\forall i\in[1,n],a_i=A_{l+i-1}+d,b_i=B_{l+i-1}
∀i∈[1,n],ai=Al+i−1+d,bi=Bl+i−1
若
o
p
t
=
B
opt=B
opt=B:
∀
i
∈
[
1
,
n
]
,
a
i
=
A
l
+
i
−
1
,
b
i
=
B
l
+
i
−
1
+
d
\forall i\in[1,n],a_i=A_{l+i-1},b_i=B_{l+i-1}+d
∀i∈[1,n],ai=Al+i−1,bi=Bl+i−1+d
求
m
i
n
(
m
a
x
{
a
1
,
a
2
,
.
.
.
,
a
p
,
b
p
+
1
,
b
p
+
2
,
.
.
.
,
b
n
}
∣
0
≤
p
≤
n
)
min(max\{a_1,a_2,...,a_p,b_{p+1},b_{p+2},...,b_n\}|0\leq p\leq n)
min(max{a1,a2,...,ap,bp+1,bp+2,...,bn}∣0≤p≤n)
题解:
记
m
a
x
a
=
m
a
x
{
a
1
,
a
2
,
.
.
.
,
a
p
}
max_a=max\{a_1,a_2,...,a_p\}
maxa=max{a1,a2,...,ap},随着
p
p
p的增大,
m
a
x
a
max_a
maxa单调不降。
记
m
a
x
b
=
m
a
x
{
b
p
+
1
,
b
p
+
2
,
.
.
.
,
b
n
}
max_b=max\{b_{p+1},b_{p+2},...,b_n\}
maxb=max{bp+1,bp+2,...,bn},随着
p
p
p的增大,
m
a
x
b
max_b
maxb单调不升。
m
a
x
(
m
a
x
a
,
m
a
x
b
)
max(max_a,max_b)
max(maxa,maxb)一定先不升,再不降,因此最优的
p
p
p可以二分得到:
若
p
=
m
i
d
p=mid
p=mid时,
- m a x a > m a x b max_a>max_b maxa>maxb,那么最优的 p p p在 [ l , m i d ] [l,mid] [l,mid]中;
- m a x a ≤ m a x b max_a\leq max_b maxa≤maxb,那么最优的 p p p在 [ m i d + 1 , r ] [mid+1,r] [mid+1,r]中。
可以用线段树上二分来得到最优的 p p p。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pr;
#define FR first
#define SE second
namespace IO{
char buf[1000010],*cur=buf+1000010;
inline char getc(){
(cur==buf+1000010)?fread(cur=buf,1,1000010,stdin):0;
return *cur++;
}
char buff[1000010],*curr=buff;
inline void flush(){
fwrite(buff,1,curr-buff,stdout);
}
inline void putc(const char &ch){
(curr==buff+1000010)?fwrite(curr=buff,1,1000010,stdout):0;
*curr++=ch;
}
inline void rd(int &x){
x=0;char ch=getc();int f=1;
while(ch<'0'||ch>'9'){
if(ch=='-')f=-1;
ch=getc();
}
while(ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getc();
}
x*=f;
}
char st[60];int tp;
void PT(int x){
if(x==0)putc('0');
else{
if(x<0){
putc('-');
x=-x;
}
while(x>0){
st[++tp]=x%10+'0';
x/=10;
}
}
while(tp)putc(st[tp--]);
}
}
using IO::getc;
using IO::putc;
using IO::rd;
using IO::PT;
int n,q;
const int N=1000010;
int maxa[N<<2],maxb[N<<2],tga[N<<2],tgb[N<<2];
int A[N],B[N];
void pushup(int u){
maxa[u]=max(maxa[u<<1],maxa[u<<1|1]);
maxb[u]=max(maxb[u<<1],maxb[u<<1|1]);
}
void Add(int u,int x,int y){
maxa[u]+=x;maxb[u]+=y;
tga[u]+=x;tgb[u]+=y;
}
void pushdown(int u){
Add(u<<1,tga[u],tgb[u]);
Add(u<<1|1,tga[u],tgb[u]);
tga[u]=tgb[u]=0;
}
void build(int u,int l,int r){
if(l==r){
maxa[u]=A[l];
maxb[u]=B[l];
return;
}
int mid=(l+r)>>1;
build(u<<1,l,mid);
build(u<<1|1,mid+1,r);
pushup(u);
}
void update(int u,int l,int r,int L,int R,int d,bool ty){
if(l==L&&r==R){
if(ty) Add(u,d,0);
else Add(u,0,d);
return;
}
pushdown(u);
int mid=(l+r)>>1;
if(R<=mid) update(u<<1,l,mid,L,R,d,ty);
else if(mid<L) update(u<<1|1,mid+1,r,L,R,d,ty);
else{
update(u<<1,l,mid,L,mid,d,ty);
update(u<<1|1,mid+1,r,mid+1,R,d,ty);
}
pushup(u);
}
pr ans[N<<2];
void pre(int u,int l,int r,int L,int R){
if(l==L&&r==R){
ans[u]=pr(maxa[u],maxb[u]);
return;
}
pushdown(u);
int mid=(l+r)>>1;
if(R<=mid){
pre(u<<1,l,mid,L,R);
ans[u]=ans[u<<1];
}
else if(mid<L){
pre(u<<1|1,mid+1,r,L,R);
ans[u]=ans[u<<1|1];
}else{
pre(u<<1,l,mid,L,mid);
pre(u<<1|1,mid+1,r,mid+1,R);
ans[u].FR=max(ans[u<<1].FR,ans[u<<1|1].FR);
ans[u].SE=max(ans[u<<1].SE,ans[u<<1|1].SE);
}
}
int solve(int u,int l,int r,int L,int R){
if(l==L&&r==R){
if(l==r) return min(maxa[u],maxb[u]);
int mid=(l+r)>>1;
pushdown(u);
int s1=maxa[u<<1],s2=maxb[u<<1|1];
if(s1>s2) return min(s1,max(s2,solve(u<<1,l,mid,l,mid)));
else return min(s2,max(s1,solve(u<<1|1,mid+1,r,mid+1,r)));
}
int mid=(l+r)>>1;
if(R<=mid) return solve(u<<1,l,mid,L,R);
else if(mid<L) return solve(u<<1|1,mid+1,r,L,R);
else{
int s1=ans[u<<1].FR,s2=ans[u<<1|1].SE;
if(s1>s2) return min(s1,max(s2,solve(u<<1,l,mid,L,mid)));
else return min(s2,max(s1,solve(u<<1|1,mid+1,r,mid+1,R)));
}
}
char opt[10];
int main(){
rd(n);rd(q);
for(int i=1;i<=n;i++) rd(A[i]);
for(int i=1;i<=n;i++) rd(B[i]);
build(1,1,n);
int l,r,d;
while(q--){
char c=getc();
while(c!='A'&&c!='B')c=getc();
rd(l);rd(r);rd(d);
if(c=='A')update(1,1,n,l,r,d,1);
else update(1,1,n,l,r,d,0);
rd(l);rd(r);
pre(1,1,n,l,r);
PT(solve(1,1,n,l,r));putc('\n');
}
IO::flush();
return 0;
}