Skip to content

线段树上二分 ​

cpp
// 求max(a_l,..a_r)=min(b_l,....,b_r)的[l,r]数量
//mx单增,mn是单减,枚举左端点,二分第一个(mx>=mn)的位置L,第一个(mx>mn)的位置R,答案为R-L
struct Node{
    int l,r,mx,mn;
};
struct SegmentTree{
    vector<Node> t;
    int n,MX,MN;
    void init(int n){
        t=vector<Node> (n<<2);
    }
    void pushup(int p){
        t[p].mx=max(t[p<<1].mx,t[p<<1|1].mx);
        t[p].mn=min(t[p<<1].mn,t[p<<1|1].mn);
    }
    void build(int p,int l,int r,vector<int>&a,vector<int>&b){
        t[p]={l,r,0,0};
        if(l==r){
            t[p].mx=a[l];
            t[p].mn=b[l];
            return;
        }
        int mid=l+r>>1;
        build(p<<1,l,mid,a,b);
        build(p<<1|1,mid+1,r,a,b);
        pushup(p);
    }
    int query1(int p,int l,int r){//找大于
        int mid=t[p].l+t[p].r>>1;
        if(l<=t[p].l&&r>=t[p].r){
            int tmx=max(MX,t[p].mx);
            int tmn=min(MN,t[p].mn);
            if(tmx<=tmn){
                MX=tmx;
                MN=tmn;
                return t[p].r+1;
            }
            if(t[p].l==t[p].r)return t[p].l;
            int now=query1(p<<1,l,r);
            if(now==mid+1)return query1(p<<1|1,l,r);
            return now;
        }
        if(l<=mid&&r>mid){
            int now=query1(p<<1,l,r);
            if(now==mid+1)return query1(p<<1|1,l,r);
            return now;
        }
        if(l<=mid)return query1(p<<1,l,r);
        return query1(p<<1|1,l,r);
    }
    int query2(int p,int l,int r){//找大于等于
        int mid=t[p].l+t[p].r>>1;
        if(l<=t[p].l&&r>=t[p].r){
            int tmx=max(MX,t[p].mx);
            int tmn=min(MN,t[p].mn);
            if(tmx<tmn){
                MX=tmx;
                MN=tmn;
                return t[p].r+1;
            }
            if(t[p].l==t[p].r)return t[p].l;
            int now=query2(p<<1,l,r);
            if(now==mid+1)return query2(p<<1|1,l,r);
            return now;
        }
        if(l<=mid&&r>mid){
            int now=query2(p<<1,l,r);
            if(now==mid+1)return query2(p<<1|1,l,r);
            return now;
        }
        if(l<=mid)return query2(p<<1,l,r);
        return query2(p<<1|1,l,r);
    }
    void clear(){
        MX=-INF;
        MN=INF;
    }
};