Just h-index
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 132768/132768 K (Java/Others)Total Submission(s): 228 Accepted Submission(s): 107
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.
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.
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.
## 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 31 5 3 2 11 32 41 55 11 2 3 4 51 5
Sample Output
2223
Source
Recommend
liuyiding
题解:
一种二分枚举 citations(mid)
再求出[mid,n]的和,即大于等于mid有多少篇论文cnt.主席树的查询操作O(logn)
然后判断cnt是否大于等于mid,进行二分
时间复杂度: O(n*logn + q*logn*logn)
代码:
//#include<bits/stdc++.h>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
using namespace std;
const int maxn = 1e5+10;
const int inf = 0x3f3f3f3f;
int arr[maxn];
int root[maxn],tot;
inline void init() {
memset(root,0,sizeof(root));
tot = 0;
}
struct SegTree
{
int lson[maxn<<5],rson[maxn<<5],sum[maxn<<5];
void init() {
memset(lson,0,sizeof(lson));
memset(rson,0,sizeof(rson));
memset(sum,0,sizeof(sum));
}
void push_up(int rt) {
sum[rt] = sum[lson[rt]] + sum[rson[rt]];
}
void build(int l,int r,int& rt) {
rt = ++tot;
if(l == r) {
sum[rt] = 0;
return;
}
int mid = (l+r)>>1;
build(l,mid,lson[rt]);
build(mid+1,r,rson[rt]);
push_up(rt);
}
void update(int pos,int val,int l,int r,int ord,int &rt) {
rt = ++tot;
lson[rt] = lson[ord];
rson[rt] = rson[ord];
if(l == r) {
sum[rt] = sum[ord] + val;///
return;
}
int mid = (l+r)>>1;
if(pos <= mid) update(pos,val,l,mid,lson[ord],lson[rt]);
else update(pos,val,mid+1,r,rson[ord],rson[rt]);
push_up(rt);
}
int query(int pos,int l,int r,int lrt,int rrt) {
if(l == r) return sum[rrt] - sum[lrt];
int mid = (l + r) >> 1;
if(pos <= mid)return sum[rson[rrt]] - sum[rson[lrt]] + query(pos,l,mid,lson[lrt],lson[rrt]);
return query(pos,mid+1,r,rson[lrt],rson[rrt]);
}
}seg;
int main()
{
int n,q;
while(~scanf("%d%d",&n,&q))
{
init();
//seg.init();
seg.build(1,n,root[0]);
//printf("%d %d %d\n",root[0],seg.lson[root[0]],seg.rson[root[0]]);
for(int i=1;i<=n;i++) scanf("%d",&arr[i]);
for(int i=1;i<=n;i++) seg.update(arr[i],1,1,n,root[i-1],root[i]);
while(q--)
{
int x,y;
scanf("%d%d",&x,&y);
int l = 0,r = inf;
while(l<=r) {
int mid = (l+r) >> 1;
int ans = seg.query(mid,1,n,root[x-1],root[y]);
if(ans >= mid) l = mid + 1;
else r = mid - 1;
}
printf("%d\n",r);
}
}
return 0;
}
我们可以发现这个二分其实是没有必要的.
在主席树的查询操作中我们就可以二分出其位置
时间复杂度 O((n+q)logn)
代码:
//#include<bits/stdc++.h>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
using namespace std;
const int maxn = 1e5+10;
int arr[maxn];
int root[maxn],tot;
inline void init() {
memset(root,0,sizeof(root));
tot = 0;
}
struct SegTree
{
int lson[maxn<<5],rson[maxn<<5],sum[maxn<<5];
void push_up(int rt) {
sum[rt] = sum[lson[rt]] + sum[rson[rt]];
}
void build(int l,int r,int& rt) {
rt = ++tot;
if(l == r) {
sum[rt] = 0;
return;
}
int mid = (l+r)>>1;
build(l,mid,lson[rt]);
build(mid+1,r,rson[rt]);
push_up(rt);
}
void update(int pos,int val,int l,int r,int ord,int &rt) {
rt = ++tot;
lson[rt] = lson[ord];
rson[rt] = rson[ord];
if(l == r) {
/// sum[rt] += val; 唔!这里有个Bug,还好比赛前发现了
sum[rt] = sum[ord] + val;
return ;
}
int mid = (l+r)>>1;
if(pos <= mid) update(pos,val,l,mid,lson[ord],lson[rt]);
else update(pos,val,mid+1,r,rson[ord],rson[rt]);
push_up(rt);
}
/// 直接在主席树中查询其位置
int query(int l,int r,int pre,int rt,int s) {
if(l == r) return l;
int cnt = sum[rson[rt]] - sum[rson[pre]];
int mid = (l+r)>>1;
if(mid+1 <= cnt+s) return query(mid+1,r,rson[pre],rson[rt],s);
return query(l,mid,lson[pre],lson[rt],s+cnt);
}
}seg;
int main()
{
int n,q;
while(~scanf("%d%d",&n,&q))
{
init();
seg.build(1,n,root[0]);
for(int i=1;i<=n;i++) scanf("%d",&arr[i]);
for(int i=1;i<=n;i++) {
seg.update(arr[i],1,1,n,root[i-1],root[i]);
}
while(q--)
{
int x,y;
scanf("%d%d",&x,&y);
printf("%d\n",seg.query(1,n,root[x-1],root[y],0));
}
}
return 0;
}