因为一个区间内的广告高度受限于最高的篱笆的高度,所以可以将所有的篱笆从高到低插入,成为一棵可持久化线段树。
维护区间内最长连续篱笆的长度
对每个询问,二分答案然后检查是否存在长度超过w的篱笆段
#include<bits/stdc++.h>
using namespace std;
#define N 100005
#define cint const int &
int tot,n,m,L,R,aim,w,root[N],l,r;
struct que{int h,i;friend bool operator < (que a,que b){return b.h<a.h;}}p[N];
struct node{int mx,l,r,lson,rson;bool tag;}t[N*25],ans;
inline void merge(node &a,node b,const node &c)
{
a.tag=(b.tag&&c.tag);
if (b.tag) a.l=b.l+c.l;else a.l=b.l;
if (c.tag) a.r=b.r+c.r;else a.r=c.r;
a.mx=max(max(max(b.mx,c.mx),max(a.l,a.r)),max(b.r+c.l,a.mx));
}
void insert(int &k,cint lk,cint l,cint r)
{
if (!k) k=++tot;
if (l==r){t[k].mx=t[k].l=t[k].r=t[k].tag=1;return;}
int mid=l+r>>1;
if (aim<=mid){insert(t[k].lson,t[lk].lson,l,mid);t[k].rson=t[lk].rson;}
else {insert(t[k].rson,t[lk].rson,mid+1,r);t[k].lson=t[lk].lson;}
merge(t[k],t[t[k].lson],t[t[k].rson]);
}
#define Lson t[k].lson,l,mid
#define Rson t[k].rson,mid+1,r
void build(int &k,cint l,cint r)
{
k=++tot;
if (l==r) return;
int mid=l+r>>1;
build(Lson);build(Rson);
}
void find(cint k,cint l,cint r)
{
if (L<=l && r<=R) return merge(ans,ans,t[k]);
int mid=l+r>>1;
if (L<=mid) find(Lson);
if (mid<R) find(Rson);
}
inline bool judge(cint k)
{
ans=(node){0,0,0,0,0,0};
find(root[k],1,n);
return w<=ans.mx;
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%d",&p[i].h),p[i].i=i;
sort(p+1,p+n+1);
build(root[0],1,n);
for (int i=1;i<=n;i++) aim=p[i].i,insert(root[i],root[i-1],1,n);
scanf("%d",&m);
while (m--)
{
scanf("%d%d%d",&L,&R,&w);
l=1,r=n;
for (int mid=l+r>>1;l<r;mid=l+r>>1) if (judge(mid)) r=mid;else l=mid+1;
printf("%d\n",p[l].h);
}
}