题意:输入第一行给了(n),(q),代表有(n)个数(q)次询问,第二行给出这(n)个数,每次询问一个区间,答出一个最大的数(h)使得这个区间里大于等于(h)的数的个数大于等(h)。
题解:见代码吧,比较好理解的,主席树
AC_Code:
1 //主席树是多个权值线段树 2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 using namespace std; 8 typedef long long ll; 9 typedef long double ld; 10 #define endl ' ' 11 const int inf=0x3f3f3f3f; 12 const int maxn=1e5+10; 13 const int maxm=5e5+10; 14 15 struct node{ 16 int l,r,sum; 17 }T[maxn*50]; 18 int root[maxn],cnt; 19 int n,q,a[maxn],maxx; 20 21 void update(int l,int r,int &x,int y,int pos){ 22 T[++cnt]=T[y], T[cnt].sum++, x=cnt; 23 if( l==r ) return ; 24 int mid=(l+r)>>1; 25 if( pos>mid ) update(mid+1,r,T[x].r,T[y].r,pos); 26 else update(l,mid,T[x].l,T[y].l,pos); 27 } 28 29 int query(int l,int r,int x,int y,int sum){ 30 if( l==r ) return l; //返回的就是所需的编号 31 int mid=(l+r)>>1; 32 int Rsum=T[T[y].r].sum - T[T[x].r].sum; 33 if( Rsum+sum>mid ) return query(mid+1,r,T[x].r,T[y].r,sum); //有一种前缀后缀和的感觉(好好感受一下) 34 else return query(l,mid,T[x].l,T[y].l,Rsum+sum); 35 } 36 37 int main() 38 { 39 while( ~ scanf("%d%d",&n,&q)){ 40 cnt=0; 41 memset(T,0,sizeof(T)); 42 maxx=0; 43 44 for(int i=1;i<=n;i++){ 45 scanf("%d",&a[i]); 46 maxx=max(maxx,a[i]); 47 } 48 for(int i=1;i<=n;i++){ 49 update(1,maxx,root[i],root[i-1],a[i]); 50 } 51 while( q-- ){ 52 int l,r; scanf("%d%d",&l,&r); 53 printf("%d ",query(1,maxx,root[l-1],root[r],0)); 54 } 55 } 56 return 0; 57 }