HDU - 6278 Just h-index(2018CCPC湘潭邀请赛C)

Just h-index

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


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 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
 


解题思路:读懂题意之后,直接上莫队。用树状数组维护后缀和(总-前缀和),然后二分答案即可。

当然对于求后缀和部分,可以直接用主席树求,速度更快这样就不用莫队了。


莫队+二分+树状数组

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string.h>
using namespace std;
typedef long long int ll;
const int MAXN=100015;
int N,Q;

int a[MAXN];

struct query{
    int l;
    int r;
    int id;
}q[MAXN];

int block[MAXN];
int blocksize;

bool cmp(query a,query b){
    if(block[a.l]==block[b.l])
        return a.r<b.r;
    return block[a.l]<block[b.l];
}

int ans[MAXN];

int tree[MAXN];
int tot=0;
int lowbit(int x){
    return x&-x;
}
void add(int x,int C){
    for(int i=x;i<=MAXN;i+=lowbit(i)){
        tree[i]+=C;
    }
}
int sum(int x){
    int ans=0;
    for(int i=x;i;i-=lowbit(i))
        ans+=tree[i];
    return ans;
}

bool judge(int x){
   // cout<<x<<" "<<tot<<" "<<sum(x-1)<<endl;
    if(tot-sum(x-1)-x>=0)
        return true;
    return false;
}

void solve(){

    int l=1;
    int r=1;
    tot++;
    add(a[1],1);

    for(int i=0;i<Q;i++){
       // cout<<q[i].r<<q[i].r<<endl;

        while (q[i].r > r)  {
            r++;
            add(a[r],1);
            tot++;
        }
        while (q[i].r < r){
            add(a[r],-1);
            r--;
            tot--;
        }
        while (q[i].l > l)  {
            add(a[l],-1);
            l++;
            tot--;
        }
        while (q[i].l < l)  {
            l--;
            add(a[l],1);
            tot++;
        }

        int ll=1,rr=N;
        int m;
        while(ll<=rr){
            m=(ll+rr)/2;
            if(judge(m)){
                ll=m+1;
            }
            else
                rr=m-1;
        }
        ans[q[i].id]=rr;
    }

}

int main()
{
    while(~scanf("%d%d",&N,&Q)){
        tot=0;
        memset(tree,0,sizeof(tree));

        blocksize=sqrt(N);
        for(int i=1;i<=N;i++){
            scanf("%d",&a[i]);
            block[i]=(i-1)/blocksize+1;
        }

        for(int i=0;i<Q;i++){
            scanf("%d%d",&q[i].l,&q[i].r);

            q[i].id=i;
        }

        sort(q,q+Q,cmp);
        solve();

        for(int i=0;i<Q;i++)
        {
            printf("%d\n",ans[i]);
        }
    }
    
    return 0;
}

主席树+二分

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string.h>
using namespace std;
typedef long long int ll;
const int MAXN=100015;
int N,Q;
int sum[MAXN*20];
int ls[MAXN*20];
int rs[MAXN*20];
int T[MAXN];
int tot=0;
void update(int P,int C,int l,int r,int &rt,int lrt){
    rt=++tot;
    ls[rt]=ls[lrt];
    rs[rt]=rs[lrt];
    sum[rt]=sum[lrt];
    if(l==r){
        sum[rt]+=C;
        return;
    }
    int m=(l+r)/2;
    if(P<=m)
        update(P,C,l,m,ls[rt],ls[lrt]);
    else
        update(P,C,m+1,r,rs[rt],rs[lrt]);
    sum[rt]=sum[ls[rt]]+sum[rs[rt]];
}

int query(int L,int R,int l,int r,int rt,int lrt){

    if(L<=l&&r<=R){
        return sum[lrt]-sum[rt];
    }
    int m=(l+r)/2;

    int ans=0;
    if(L<=m)
        ans+=query(L,R,l,m,ls[rt],ls[lrt]);
    if(R>m)
        ans+=query(L,R,m+1,r,rs[rt],rs[lrt]);
    return ans;
}

bool judge(int x,int l,int r){
    if(query(x,N,1,N,T[l-1],T[r])-x>=0)
        return true;
    return false;
}

int main()
{
    while(~scanf("%d%d",&N,&Q)){
        tot=0;
        memset(sum,0,sizeof(sum));
        memset(ls,0,sizeof(ls));
        memset(rs,0,sizeof(rs));
        int a;
        for(int i=1;i<=N;i++){
            scanf("%d",&a);
            update(a,1,1,N,T[i],T[i-1]);
        }
        int l,r;

        for(int i=0;i<Q;i++){
            scanf("%d%d",&l,&r);
            int ll=1,rr=N;
            int m;
            while(ll<=rr){
                m=(ll+rr)/2;
                if(judge(m,l,r)){
                    ll=m+1;
                }
                else
                    rr=m-1;
            }
            printf("%d\n",rr);

        }
    }

    return 0;
}



猜你喜欢

转载自blog.csdn.net/lzc504603913/article/details/80375264