HDU6278 Just h -index(主席树)

Just h-index

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


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

*   1n,q105
*   1ain
*   1lirin
* 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
 


题意:
给你一个长度为n的序列,有m个询问

每一个询问[l,r]询问序列中在该区间内的数最大的k下标,(k下标是满足该区间至少有k个数的值是大于k的)

解析:
k下标的意思就是满足区间内第k大数的值大于k这个条件的k,然后找这些满足条件的k中的最大值。
思路就是对每一个区间长度二分,[l,r]的话,左端点就是1,右端点就是r-l+1。
然后通过主席树找区间内的第mid大的数,这样最后二分的结果就是最大的k了


#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int MAXN = 1e5+5;
//const int MAXM = (1e5+5)*15;

typedef struct node
{
    int x;
    int id;
}node;

int a[MAXN];
int ran[MAXN];
int rt[MAXN*20],ls[MAXN*20],rs[MAXN*20],tot,sz;
int sum[MAXN*20];

bool cmp(node a,node b)
{
    return a.x<b.x;
}

void build(int& root,int l,int r)
{
    root=++tot;
    sum[root]=0;
    if(l==r) return;
    int mid=(l+r)>>1;
    build(ls[root],l,mid);
    build(rs[root],mid+1,r);

}

void update(int& root,int l,int r,int last,int x)
{
    root=++tot;
    ls[root]=ls[last];
    rs[root]=rs[last];
    sum[root]=sum[last]+1;
    if(l==r) return ;
    int mid=(l+r)>>1;
    if(mid>=x) update(ls[root],l,mid,ls[last],x);
    else update(rs[root],mid+1,r,rs[last],x);


}

int query(int ss,int tt,int l,int r,int k)
{
    if(l==r) return l;
    int cnt=sum[rs[tt]]-sum[rs[ss]];
    int mid=(l+r)>>1;
    if(k>cnt) return query(ls[ss],ls[tt],l,mid,k-cnt);
    else return query(rs[ss],rs[tt],mid+1,r,k);
}


int solve(int s,int e)
{
    int r=e-s+1;
    int l=1;
    int ans=1;
    while(l<r)
    {
        int mid=(l+r)/2;
        if(ran[query(rt[s-1],rt[e],1,sz,mid)]>=mid) l=mid+1,ans=mid;
        else r=mid;
    }
    int mid=(l+r)>>1;
    if(ran[query(rt[s-1],rt[e],1,sz,mid)]>=mid) l=mid+1,ans=mid;
    return ans;

}

int main()
{
    int t;
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF)
    {

        for(int i=1;i<=n;i++) scanf("%d",&a[i]),ran[i]=a[i];
        tot=0;
        sort(ran+1,ran+1+n);
        sz=unique(ran+1,ran+1+n)-(ran+1);
        build(rt[0],1,sz);
        for(int i=1;i<=n;i++) a[i]=lower_bound(ran+1,ran+1+sz,a[i])-ran;
        for(int i=1;i<=n;i++) update(rt[i],1,sz,rt[i-1],a[i]);
        for(int i=0;i<m;i++)
        {
            int l,r;
            scanf("%d%d",&l,&r);
            printf("%d\n",solve(l,r));
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37025443/article/details/81006457
今日推荐