CF484E. Sign on Fence(主席树+二分)

CF484E. Sign on Fence

CF484E. Sign on Fence

题目大意

给你n块木板,每块木板有高度Hi,q次询问每次询问在[l,r]区间中最大的长度为w的区间的最小值。

思路

将木板从大到小排序,建动态开点线段树维护区间最长子段,于是就可以二分高度,判断这个高度在[l,r]
区间中存不存在长度大等于w的子段。

代码

#include 
using namespace std;
#define dd(x) cout<<#x<<" = "< vi; 
typedef  pair pi;
bool cmp(const pi&a,const pi&b){return a.fi>b.fi;}
pi a[maxn];
int n,q,cnt, T[maxn];
struct node {
    int ls,rs,l,r,s;
    node (){ls=rs=l=r=s=0;}
}t[maxn<<5];
void push_up(int rt,int m){
    int ls=t[rt].ls, rs = t[rt].rs;
    int rm = m>>1, lm = m-rm;
    t[rt].l = t[ls].l;
    if(t[ls].l == lm) t[rt].l += t[rs].l;
    
    t[rt].r = t[rs].r;
    if(t[rs].r == rm) t[rt].r += t[ls].r;
    
    t[rt].s = max(t[rs].l+t[ls].r,max(t[rs].s,t[ls].s));
    return ;
}
void update(int pre,int &now,int pos,int l,int r){
    now = ++cnt;
    if(l==r){
        t[now].l = t[now].r = t[now].s = 1;
        return ;
    }
    t[now].ls = t[pre].ls;
    t[now].rs = t[pre].rs;
    int mid = l+r>>1;
    if(pos <=mid) update(t[pre].ls,t[now].ls,pos,l,mid);
    else update(t[pre].rs,t[now].rs,pos,mid+1,r);
    push_up(now,r-l+1); 
}
node qry(int now,int L,int R,int l,int r){
    if(L<=l && r<=R){
        return t[now];
    }
    int mid = l+r>>1, m=r-l+1, rm=m>>1, lm=m-rm;
    node ls,rs,ans;
    if(L <= mid) ls = qry(t[now].ls,L,R,l,mid);
    if(R > mid) rs = qry(t[now].rs,L,R,mid+1,r);
    ans.l = ls.l;
    if(ls.l == lm) ans.l+=rs.l;
    ans.r = rs.r;
    if(rs.r == rm) ans.r+=ls.r;
    ans.s = max(ls.r+rs.l,max(ls.s,rs.s));
    return ans;
}
int check(int l,int r,int h,int rt){
    if(qry(T[rt],l,r,1,n).s >= h) return 1;
    return 0;
}
int main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0); 
    cin >> n;
    rep(i,1,n+1) cin >> a[i].fi , a[i].se = i;
    sort(a+1,a+n+1,cmp);
    rep(i,1,n+1){
        update(T[i-1],T[i],a[i].se,1,n);
    }
    cin>> q;
    while(q--){
        int x, y ,m;
        cin >> x >> y >> m;
        int l=1,r=n;
        while(l<=r){
            int mid = l+r>>1;
            if(check(x,y,m,mid)) r=mid-1;
            else l=mid+1;
        }
        r++;
        cout << a[r].fi << endl;
    }    
    return 0;
}

你可能感兴趣的:(CF484E. Sign on Fence(主席树+二分))