[XSY4170] 妹子(线段树上二分)

传送门

题意:
给出两个长度为 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=rl+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+i1+d,bi=Bl+i1
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+i1,bi=Bl+i1+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}0pn)

题解:
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 maxamaxb,那么最优的 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;
}

猜你喜欢

转载自blog.csdn.net/Emma2oo6/article/details/121405087