(银牌区)CCPC2018-湖南全国邀请赛 C. Just h-index HDU - 6278 主席树+二分

博客目录

原题 (吐槽一下题目描述非常绕口)

oj传送门

下面粘贴的格式不太好,参考pdf或者原题链接:

比赛题目: 
http://acm.hdu.edu.cn/downloads/2018ccpc_hn.pdf 
The hh-index of an author is the largest hh where he has at least hh papers with citations not less than hh. 

Bobo has published nn papers with citations a1,a2,…,ana1,a2,…,an respectively. 
One day, he raises qq questions. The ii-th question is described by two integers lili and riri, asking the hh-index of Bobo if has *only* published papers with citations ali,ali+1,…,ariali,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 nn and qq. 
The second line contains nn integers a1,a2,…,ana1,a2,…,an. 
The ii-th of last qq lines contains two integers lili and riri. 

Output

For each question, print an integer which denotes the answer. 

## Constraint 

* 1≤n,q≤1051≤n,q≤105 
* 1≤ai≤n1≤ai≤n 
* 1≤li≤ri≤n1≤li≤ri≤n 
* The sum of nn does not exceed 250,000250,000. 
* The sum of qq does not exceed 250,000250,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

题目大意:

在一个区间内求一个h,h满足区间内至少有h个数大于等于h

二分h(1到区间长度len),对于每个h检查是不是有h个大于等于它,也就是看看第h大是不是大于等于它 ,所以用主席树查询区间第k大的数

AC代码

#include <bits/stdc++.h>
#include <cstring>
using namespace std;
typedef long long ll;
const int maxn=2e5+5e4+10;
const int M=maxn*100;
int n,q,m,tot;
int a[maxn],t[maxn];
int T[maxn],lson[M],rson[M],c[M];
void init_hs(){
    for(int i=1;i<=n;i++)
        t[i]=a[i];
    sort(t+1,t+1+n);
    m=unique(t+1,t+1+n)-t-1;
}
int build(int l,int r){
    int root = tot++;
    c[root]=0;
    if(l!=r){
        int mid=(l+r)>>1;
        lson[root]=build(l,mid);
        rson[root]=build(mid+1,r);
    }
    return root;
}
int hs(int x){
    return lower_bound(t+1,t+1+m,x)-t;
}
int update(int root ,int pos,int val){
    int newroot=tot++,tmp=newroot;
    c[newroot]=c[root]+val;
    int l=1,r=m;
    while(l<r){
        int mid=(l+r)>>1;
        if(pos<=mid){
            lson[newroot]=tot++;
            rson[newroot]=rson[root];
            newroot=lson[newroot];
            root=lson[root];
            r=mid;
        }
        else{
            rson[newroot]=tot++;
            lson[newroot]=lson[root];
            newroot=rson[newroot];
            root=rson[root];
            l=mid+1;
        }
        c[newroot]=c[root]+val;
    }
    return tmp;
}
int query(int left_root,int right_root,int k){
    int l=1,r=m;
    while(l<r){
        int mid=(l+r)>>1;
        if(c[lson[left_root]]-c[lson[right_root]]>=k){
            r=mid;
            left_root=lson[left_root];
            right_root=lson[right_root];
        }
        else{
            l=mid+1;
            k-=c[lson[left_root]]-c[lson[right_root]];
            left_root=rson[left_root];
            right_root=rson[right_root];
        }
    }
    return l;
}
inline int check(int num,int x){  
    if(num<=x){
        return 1;
    }else{
        return 0;
    }
}

int number[maxn];//元数据存档 
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("r.txt","r",stdin);
    #endif 
    while(scanf("%d%d",&n,&q)!=EOF){
        tot=0;
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        init_hs();
        T[n+1]=build(1,m);
        for(int i=n;i;i--){
            int pos=hs(a[i]);
            T[i]=update(T[i+1],pos,1);
        }
        int tmp;
        while(q--){
            int x,y,l,r,mid;
            int t1,t2;
            scanf("%d%d",&x,&y);
            int len=y-x+1;
            l=1;
            r=len; //h只能在1到len之间。 
            while(l<r){
                mid=(l+r)>>1;
                t1=t[query(T[x],T[y+1],len-mid+1)];
                t2=t[query(T[x],T[y+1],len-(mid+1)+1)]; //二分h,对于每个h(mid)检查是不是有h个大于等于它,也就是看看第h大是不是大于等于它 
                if(check(mid,t1)){
                    if(check(mid+1,t2)){
                        l=mid+1;
                    }
                    else{
                        l=mid;
                        break;
                    }
                }else{
                    r=mid-1;
                }
            }
            printf("%d\n",l);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/GreyBtfly/article/details/82912310
今日推荐