题意:多组样例 n,m;a1,a2,ai…an;m次询问;
每次询问是:找到一个最大的 x 使区间[l,r]内的数(ai)>=x的数 的个数>=x;
(这个x是任意一个数)
思路:low=1,high=r-l+1(一个区间内最多有r-l+1个数)。
查询的mid也应该refl一下,mid的范围[0,n]。refl数组也应该加上1-n;
(但是这个数应该与mid比较是否>=,不要弄混了)
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define m(a,b) memset(a,b,sizeof a)
#define en '\n'
using namespace std;
typedef long long ll;
const int N=25e4;
struct tree{int l,r;}t[N*100];
int root[N],sum[N*100],sz;
int a[N],refl[N<<1],tot;
void build(int wh,int &x,int y,int l,int r)
{
x=++sz,t[x]=t[y],sum[x]=sum[y]+1;
if(l==r)
return;
int mid=(l+r)>>1;
if(wh<=mid)
build(wh,t[x].l,t[y].l,l,mid);
else
build(wh,t[x].r,t[y].r,mid+1,r);
}
int query(int x,int y,int val,int l,int r)
{
if(l==r)
return sum[y]-sum[x];
int mid=(l+r)>>1;
if(val<=mid)
return sum[t[y].r]-sum[t[x].r]+query(t[x].l,t[y].l,val,l,mid);
else
return query(t[x].r,t[y].r,val,mid+1,r);
}
int judge(int mid,int x,int l,int r)//判断 区间[l,r]内ai>=x的个数是否>=x;
{
return query(root[l-1],root[r],x,1,tot)>=mid;
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
sz=0,tot=0,m(sum,0);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]),refl[++tot]=i,refl[++tot]=a[i];
sort(refl+1,refl+tot+1);
tot=unique(refl+1,refl+tot+1)-(refl+1);
for(int i=1;i<=n;i++)
{
int dex=lower_bound(refl+1,refl+tot+1,a[i])-refl;
build(dex,root[i],root[i-1],1,tot);
}
while(m--)
{
int l,r;scanf("%d%d",&l,&r);
int low=1,high=r-l+1,mid,dex;
while(low<=high)
{
mid=(low+high)>>1;
dex=lower_bound(refl+1,refl+tot+1,mid)-refl;
if(judge(mid,dex,l,r))
low=mid+1;
else
high=mid-1;
}
printf("%d\n",low-1);
}
}
}