题:http://acm.hdu.edu.cn/showproblem.php?pid=6278
题意:求区间中最大的x,满足大于等于x的数量大于等于x
分析:二分找答案,check(mid)为查询区间中第len-mid+1大的数是否大于mid
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; #define pb push_back #define MP make_pair #define lson root<<1,l,midd #define rson root<<1|1,midd+1,r typedef long long ll; const int mod=10007; const int M=2e5+5; const int inf=0x3f3f3f3f; const ll INF=1e18; int a[M],b[M]; struct ChairTree{ int root[M],cnt; struct node{ int sum,L,R; }tr[M*40]; void Clear(int n){ for(int i=0;i<=n;i++) tr[i].sum=tr[i].L=tr[i].R=0; } void update(int &rt,int pos,int l,int r){ tr[++cnt]=tr[rt]; tr[cnt].sum++; rt=cnt; if(l==r) return; int midd=(l+r)>>1; if(pos<=midd) update(tr[rt].L,pos,l,midd); else update(tr[rt].R,pos,midd+1,r); } int query(int i,int j,int k,int l,int r){ int num=tr[tr[j].L].sum-tr[tr[i].L].sum; if(l==r) return l; int midd=(l+r)>>1; if(num>=k) return query(tr[i].L,tr[j].L,k,l,midd); else return query(tr[i].R,tr[j].R,k-num,midd+1,r); } }t1; int main(){ int n,m; while(~scanf("%d%d",&n,&m)){ for(int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i]; sort(b+1,b+1+n); int p=unique(b+1,b+1+n)-b-1; t1.cnt=0; for(int i=1;i<=n;i++){ t1.root[i]=t1.root[i-1]; int pos=lower_bound(b+1,b+1+p,a[i])-b; t1.update(t1.root[i],pos,1,p); } while(m--){ int x,y; scanf("%d%d",&x,&y); int len=y-x+1; int l=0,r=len,ans=0; while(l<=r){ int midd=(l+r)>>1; if(b[t1.query(t1.root[x-1],t1.root[y],len-midd+1,1,p)]>=midd){ ans=max(ans,midd); l=midd+1; } else r=midd-1; } printf("%d ",ans); } t1.Clear(t1.cnt); } return 0; }