题意:
给出两个长度为 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;
}