题目描述
N,Q<=5e4
题解
基础线段树
先算al<=ar的,之后取反再算一次
设L[i]表示往左第一个大于当前的位置+1,R[i]是往右小于的-1
那么区间[l,r]满足条件当且仅当R[l]>=r且L[r]<=l
枚举右端点,在x处维护[x,x~r]的最大值,考虑r-1->r的变化
加入的区间[x,r]需要满足R[x]>=r,L[r]<=x,即对满足R[x]>=r的x∈[L[r],r]的更新
按照R[x]排序单调单点删R[x]<r的,维护区间最小值和答案,询问直接查[L,R]
code
#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define inf 2147483647
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
#define ll long long
//#define file
using namespace std;
struct type{int l,r,id;} q[50001];
struct Type{int x,id;} b[50001];
int tr[200001][2],Tr[200001],a[50001],L[50001],R[50001],d[50001],ans[50001],h,t,n,i,j,k,l,Q,Find;
bool Cmp(Type a,Type b) {return a.x<b.x;}
bool cmp(type a,type b) {return a.r<b.r;}
void mt(int t,int l,int r)
{
int mid=(l+r)/2;
Tr[t]=tr[t][0]=tr[t][1]=0;
if (l==r) {tr[t][1]=l;return;}
mt(t*2,l,mid);
mt(t*2+1,mid+1,r);
tr[t][1]=min(tr[t*2][1],tr[t*2+1][1]);
}
void down(int t,int len)
{
if (Tr[t])
{
if (len>1)
Tr[t*2]=Tr[t],Tr[t*2+1]=Tr[t];
tr[t][0]=max(tr[t][0],Tr[t]-tr[t][1]+1);
Tr[t]=0;
}
}
void change(int t,int l,int r,int x,int y,int s)
{
int mid=(l+r)/2;
down(t,r-l+1);
if (x<=l && r<=y) {Tr[t]=s;down(t,r-l+1);return;}
down(t*2,mid-l+1);
down(t*2+1,r-mid);
if (x<=mid) change(t*2,l,mid,x,y,s);
if (mid<y) change(t*2+1,mid+1,r,x,y,s);
tr[t][0]=max(tr[t*2][0],tr[t*2+1][0]);
}
void Change(int t,int l,int r,int x)
{
int mid=(l+r)/2;
down(t,r-l+1);
if (l==r) {tr[t][1]=inf;return;}
down(t*2,mid-l+1);
down(t*2+1,r-mid);
if (x<=mid) Change(t*2,l,mid,x);
else Change(t*2+1,mid+1,r,x);
tr[t][1]=min(tr[t*2][1],tr[t*2+1][1]);
}
void find(int t,int l,int r,int x,int y)
{
int mid=(l+r)/2;
down(t,r-l+1);
if (x<=l && r<=y) {Find=max(Find,tr[t][0]);return;}
if (x<=mid) find(t*2,l,mid,x,y);
if (mid<y) find(t*2+1,mid+1,r,x,y);
}
void work()
{
t=0;d[0]=0;
fo(i,1,n)
{
while (t && a[d[t]]<=a[i]) --t;
L[i]=d[t]+1;
d[++t]=i;
}
t=0;d[0]=n+1;
fd(i,n,1)
{
while (t && a[d[t]]>=a[i]) --t;
R[i]=d[t]-1;
d[++t]=i;
}
fo(i,1,n) b[i]={R[i],i};
sort(b+1,b+n+1,Cmp);
mt(1,1,n),j=1,k=1;
fo(i,1,n)
{
while (j<=n && b[j].x<i) Change(1,1,n,b[j].id),++j;
change(1,1,n,L[i],i,i);
while (k<=Q && q[k].r==i) Find=0,find(1,1,n,q[k].l,q[k].r),ans[q[k].id]=max(ans[q[k].id],Find),++k;
}
}
int main()
{
#ifdef file
freopen("b.in","r",stdin);
freopen("a.out","w",stdout);
#endif
scanf("%d",&n);
fo(i,1,n) scanf("%d",&a[i]);
scanf("%d",&Q);
fo(i,1,Q) scanf("%d%d",&q[i].l,&q[i].r),q[i].id=i;
sort(q+1,q+Q+1,cmp);
work();
fo(i,1,n) a[i]=-a[i];
work();
fo(i,1,Q) printf("%d
",ans[i]);
fclose(stdin);
fclose(stdout);
return 0;
}