HDU 6278 主席树(区间第k大)+二分

Posted stranger-

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 6278 主席树(区间第k大)+二分相关的知识,希望对你有一定的参考价值。

Just h-index

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


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
 

 

Source

补:主席树  2018湘潭C http://acm.hdu.edu.cn/showproblem.php?pid=6278

代码    

#include<bits/stdc++.h>
using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
const LL INF = 1E9+9;

const int maxn = 1000006;
const int LOG = 20;

struct node
{
    int l,r;
    int sum;
}Node[maxn*LOG];
int root[maxn],node_cnt;
int numbers[maxn],num_cnt;
int a[maxn];

void build(int l,int r,int &rt)
{
    rt=++node_cnt;
    Node[rt].l=Node[rt].r=Node[rt].sum=0;
    if(l==r)
        return ;
    int m=(l+r)>>1;
    build(l,m,Node[rt].l);
    build(m+1,r,Node[rt].r);
}
void update(int v,int l,int r,int &rt,int pre)
{
    rt=++node_cnt;
    Node[rt]=Node[pre];
    ++Node[rt].sum;
    if(l==r)
        return ;
    int m=(l+r)>>1;
    if(v<=m)
        update(v,l,m,Node[rt].l,Node[pre].l);
    else
        update(v,m+1,r,Node[rt].r,Node[pre].r);
}
int query(int k,int l,int r,int r1,int r2)
{
    if(l==r)
        return r;
    int lnum=Node[Node[r2].l].sum-Node[Node[r1].l].sum;
    int m=(l+r)>>1;
    if(k<=lnum)
        return query(k,l,m,Node[r1].l,Node[r2].l);
    else
        return query(k-lnum,m+1,r,Node[r1].r,Node[r2].r);
}

int main()
{
//    ios::sync_with_stdio(false);
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
    //        cin>>a[i];
            numbers[i]=a[i];
        }
        sort(numbers+1,numbers+n+1);
        num_cnt=unique(numbers+1,numbers+n+1)-numbers-1;
        node_cnt=0;
        root[0]=0;
        build(1,num_cnt,root[0]);
        for(int i=1;i<=n;i++)
        {
            int pos = lower_bound(numbers+1,numbers+num_cnt+1,a[i])-numbers;
            update(pos,1,num_cnt,root[i],root[i-1]);
        }
        while(m--)
        {
            int L,R,K;
            cin>>L>>R;
            int l=1,r=R-L+1;
            int ans=1;
            //int q=query(K,1,num_cnt,root[L-1],root[R]);
            //cout<<numbers[q]<<endl;
            while(l<=r)
            {
                int mid=(l+r)/2;
                int q=query(R-L+2-mid,1,num_cnt,root[L-1],root[R]);
                //cout<<"mid="<<mid<<" val="<<numbers[q]<<endl;
                if(numbers[q]>=mid)
                {
                    ans=max(mid,ans);
                    l=mid+1;
                }
                else
                    r=mid-1;

            }
            printf("%d
",ans);
        }
    }
    return 0;
}

 























以上是关于HDU 6278 主席树(区间第k大)+二分的主要内容,如果未能解决你的问题,请参考以下文章

hdu 5919 主席树(区间不同数的个数 + 区间第k大)

HDU6278 Just h-index

主席树区间第K大

hdu 5919--Sequence II(主席树--求区间不同数个数+区间第k大)

HDU6621 K-th Closest Distance 第 k 小绝对值(主席树(统计范围的数有多少个)+ 二分 || 权值线段树+二分)

HDU - 6621 K-th Closest Distance 主席树+二分答案