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

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;
}
posted @ 2019-05-09 01:10  Seast  阅读(209)  评论(0编辑  收藏  举报