思路:二分枚举h,利用主席树求[L,R]区间内是否满足有至少h个数大于等于h。
#include
using namespace std;
const int MAX=1e5+10;
const int MOD=1e9+7;
const double PI=acos(-1.0);
typedef long long ll;
int a[MAX];
vectorv;
struct lenka
{
int L,R,sum;
}A[40*MAX];
int tot,root[MAX];
void init()
{
tot=1;
root[0]=0;
A[0].sum=A[0].L=A[0].R=0;
v.clear();
}
void build(int x,int& rt,int l,int r)
{
A[tot++]=A[rt];
rt=tot-1;
A[rt].sum++;
if(l==r)return;
if(x<=(l+r)/2)build(x,A[rt].L,l,(l+r)/2);
else build(x,A[rt].R,(l+r)/2+1,r);
}
int ask(int l,int r,int x,int y,int k)
{
if(l==r)return A[y].sum-A[x].sum;
if(k>(l+r)/2)return ask((l+r)/2+1,r,A[x].R,A[y].R,k);
return A[A[y].R].sum-A[A[x].R].sum+ask(l,(l+r)/2,A[x].L,A[y].L,k);
}
int getid(int x){return lower_bound(v.begin(),v.end(),x)-v.begin()+1;;}
int main()
{
int n,q;
while(scanf("%d%d",&n,&q)!=EOF)
{
init();
for(int i=1;i<=n;i++)scanf("%d",&a[i]),v.push_back(a[i]);
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
for(int i=1;i<=n;i++)
{
root[i]=root[i-1];
build(getid(a[i]),root[i],1,n);
}
while(q--)
{
int x,y;
scanf("%d%d",&x,&y);
int l=0,r=n,ans=0;
while(r>=l)
{
int m=(l+r)/2;
if(ask(1,n,root[x-1],root[y],getid(m))>=m)
{
ans=m;
l=m+1;
}
else r=m-1;
}
printf("%d\n",ans);
}
}
return 0;
}