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

时间:2022-12-30 00:03:16

CF484E. Sign on Fence

CF484E. Sign on Fence

题目大意

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

思路

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

代码

#include <bits/stdc++.h>
using namespace std;
#define dd(x) cout<<#x<<" = "<<x<<" "
#define rep(i,a,b) for(int i=(a);i<(b);i++)
#define de(x) cout<<#x<<" = "<<x<<"\n"
#define mes(p) memset(p,0,sizeof(p))
#define fi first
#define se second
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define sz(x) (int)x.size()
#define pb push_back
#define all(x) x.begin(),x.end()
const int maxn=100005;
const int mod = 1e9+7;
const int M = 3e5;
typedef long long ll;
typedef  vector <int > vi; 
typedef  pair<int ,int > 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;
}