1. 程式人生 > >HDU 6278 主席樹(區間第k大)+二分

HDU 6278 主席樹(區間第k大)+二分

struct miss amp turn 湘潭大學 sig sin number log

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 CCPC2018-湖南全國邀請賽-重現賽(感謝湘潭大學)

補:主席樹 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\n",ans);
        }
    }
    return 0;
}

HDU 6278 主席樹(區間第k大)+二分