hdu-6278 Just h-index湘大邀请赛C题

Just h-index

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


 

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≤ain
* 1≤lirin
* 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

离散化主席树二分,静态查询第k小。

对于区间L-R容易知道答案最大为answer=R-L+1,每次二分询问answer是否符合条件,最后输出答案即可。

例如在 1 3 2 4 5 这个区间询问答案时,最大answer=5,第一次询问第3小的值有没有3个,显然符合,第二次询问第2小的值有没有4个,条件不符,所以输出answer就行了。

 

#include<bits/stdc++.h>
#define me(a) memset(a,0,sizeof a)
using namespace std;
const int maxn=1e5+6;
int root[maxn];
int a[maxn];
int b[maxn+maxn];
int cnt,size;
struct node
{
	int l,r,sum;
} sz[maxn*40];
void updata(int l,int r,int &x,int y,int pos)
{
	sz[++cnt]=sz[y];               
	sz[cnt].sum++;
	x=cnt;
	if(l==r) return ;
	int mid=(l+r)>>1;
	if(mid>=pos) updata(l,mid,sz[x].l,sz[y].l,pos);
	else updata(mid+1,r,sz[x].r,sz[y].r,pos);
}
int getSum(int l,int r,int x,int y,int p)
{
	if(l==r) return l;
	int sum=sz[sz[y].l].sum-sz[sz[x].l].sum;
	int mid=(l+r)>>1;
	if(sum>=p) return (getSum(l,mid,sz[x].l,sz[y].l,p));
	else return getSum(mid+1,r,sz[x].r,sz[y].r,p-sum);
}
int main()
{
	int n,m;
	while(~scanf("%d %d",&n,&m))
	{
		cnt=0,size=0;
		me(a); me(root);
		me(b); me(sz);
		for(int i=1; i<=n; i++)
		{
			scanf("%d",&a[i]);
			b[++size]=a[i];
		}
		sort(b+1,b+size+1);
		size=unique(b+1,b+1+size)-b-1;//离散化 
		for(int i=1; i<=n; i++)
		{
			int p=lower_bound(b+1,b+1+size,a[i])-b;
			updata(1,n,root[i],root[i-1],p);
		}
		for(int i=1; i<=m; i++)
		{
			int x,y;
			scanf("%d %d",&x,&y);
			int r=y-x+1;
			int l=1;
			int xx; 
			while(l<=r)
			{
				int mid=(l+r)>>1;
				//
				if(b[getSum(1,n,root[x-1],root[y],y-x+2-mid)]>=mid)//二分查找 
				{
					l=mid+1; 
					xx=mid;
				}
				else 
					r=mid-1;
			}
			cout<<xx<<endl;
		}
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值