CCPC2018-湖南全国邀请赛 HDU6278 Just h-index【主席树+二分查找】

Just h-index

http://acm.hdu.edu.cn/showproblem.php?pid=6278

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others)
Total Submission(s): 1250    Accepted Submission(s): 566


 

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≤10^5
* 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

Source

CCPC2018-湖南全国邀请赛-重现赛(感谢湘潭大学)

题解

主席树求区间大于等于k的个数+二分查找

C++代码

#include<iostream>
#include<algorithm>

using namespace std;

const int N=100100;

int a[N],b[N],rt[20*N],ls[20*N],rs[20*N],sum[20*N];

int id;

void build(int &o,int l,int r)
{
	o=++id;
	sum[o]=0;
	if(l==r) return;
	int m=(l+r)>>1;
	build(ls[o],l,m);
	build(rs[o],m+1,r);
}

void update(int &o,int l,int r,int last,int p)
{
	o=++id;
	ls[o]=ls[last];
	rs[o]=rs[last];
	sum[o]=sum[last]+1;
	if(l==r) return;
	int m=(l+r)>>1;
	if(p<=m)
	  update(ls[o],l,m,ls[last],p);
	else
	  update(rs[o],m+1,r,rs[last],p);
}

//查询区间[L+1,R]内大于等于k的个数
int query(int L,int R,int l,int r,int k)
{
	if(b[l]>=k) return sum[R]-sum[L];
	if(l==r) return 0;
	int m=(l+r)>>1;
	int sum=0;
	if(b[m]>=k)
	  sum+=query(ls[L],ls[R],l,m,k);
	sum+=query(rs[L],rs[R],m+1,r,k);
	return sum; 
} 

int main()
{
	int n,q;
	while(~scanf("%d%d",&n,&q))
	{
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&a[i]);
			b[i]=a[i];
		}
		sort(b+1,b+n+1);
		int size=unique(b+1,b+n+1)-(b+1);
		id=0;
		build(rt[0],1,size);
		for(int i=1;i<=n;i++)
		{
			a[i]=lower_bound(b+1,b+1+size,a[i])-b;
			update(rt[i],1,size,rt[i-1],a[i]);
		}
		while(q--)
		{
			int L,R;
			scanf("%d%d",&L,&R);
			int l=0,r=R-L+1;
			while(l<=r)
			{
				int m=(l+r)>>1;
				if(query(rt[L-1],rt[R],1,size,m)<m)
				  r=m-1;
				else
				  l=m+1; 
			}
			printf("%d\n",l-1);
		}
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值