Just h-index
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 132768/132768 K (Java/Others)
Total Submission(s): 0 Accepted Submission(s): 0
Problem Description
The h-index of an author is the largest h where he has at least h papers with citations not less than h.
Bobo has published n papers with citations a1,a2,…,an respectively.
One day, he raises q questions. The i-th question is described by two integers li and ri, asking the h-index of Bobo if has only published papers with citations ali,ali+1,…,ari.
Input
The input consists of several test cases and is terminated by end-of-file.
The first line of each test case contains two integers n and q.
The second line contains n integers a1,a2,…,an.
The i-th of last q lines contains two integers li and ri.
Output
For each question, print an integer which denotes the answer.
Constraint
- 1≤n,q≤105
- 1≤ai≤n
- 1≤li≤ri≤n
- The sum of n does not exceed 250,000.
- The sum of q does not exceed 250,000.
Sample Input
5 3 1 5 3 2 1 1 3 2 4 1 5 5 1 1 2 3 4 5 1 5
Sample Output
2 2 2 3
题目就是给我们一个区间,让我们找到一个最大的值,使得大于等于这个值的数的个数大于等于这个值。
这个就是很明显的权值线段树,但是我们要找到某个区间的权值线段树,也就是要可持久化(主席树)。
然后我们二分答案即可(似乎也可以在主席树当中二分)。
每次二分check时,判断当前我们查询的区间的大于等于mid的个数即可。
AC代码:
#pragma GCC optimize(2)
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=1e5+10;
int n,q,root[N],cnt,x;
struct node{
int l,r,sum;
}t[N<<5];
void change(int l,int r,int &x,int y,int k){
x=++cnt; t[x]=t[y]; t[x].sum++;
if(l==r) return ; int mid=l+r>>1;
if(k<=mid) change(l,mid,t[x].l,t[y].l,k);
else change(mid+1,r,t[x].r,t[y].r,k);
}
int ask(int l,int r,int x,int y,int ql,int qr){
if(l==ql&&r==qr) return t[y].sum-t[x].sum;
int mid=l+r>>1;
if(qr<=mid) return ask(l,mid,t[x].l,t[y].l,ql,qr);
else if(ql>mid) return ask(mid+1,r,t[x].r,t[y].r,ql,qr);
else return ask(l,mid,t[x].l,t[y].l,ql,mid)+ask(mid+1,r,t[x].r,t[y].r,mid+1,qr);
}
int bsearch(int ql,int qr){
int l=1,r=n;
while(l<r){
int mid=l+r+1>>1;
if(ask(1,n,root[ql-1],root[qr],mid,n)>=mid) l=mid;
else r=mid-1;
}
return l;
}
signed main(){
while(~scanf("%d %d",&n,&q)){
cnt=0;
for(int i=1;i<=n;i++) scanf("%d",&x),change(1,n,root[i],root[i-1],x);
while(q--){
int l,r; scanf("%d %d",&l,&r);
printf("%d\n",bsearch(l,r));
}
}
return 0;
}