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

* 1≤n,q≤105
* 1≤ai≤n
* 1≤li≤ri≤n
* 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;
}

原文地址:https://www.cnblogs.com/stranger-/p/9343693.html

时间: 2024-10-07 23:53:00

HDU 6278 主席树(区间第k大)+二分的相关文章

主席树区间第K大

主席树的实质其实还是一颗线段树, 然后每一次修改都通过上一次的线段树,来添加新边,使得每次改变就改变logn个节点,很多节点重复利用,达到节省空间的目的. 1.不带修改的区间第K大. HDU-2665 模板题 代码: 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt&qu

POJ 2104 K-th Number 主席树 区间第K大

今天第一次接触可持久化数据结构,还是有必要总结一下的. 首先对于查找第k大的问题,先搞清楚怎么样通过利用N颗线段树来求解.如果是求全局第K大,那么可以把数字的值作为位置插入线段树,然后通过区间和+二分来找到第k个位置.因为是通过区间和来找第k大的,显然是满足前缀和性质的,所以查询l,r区间的第k打,就直接根据1-l - 1,1-r两个区间建立两颗线段树,然后通过节点依次相减来求得第k大值.所以这样子解需要的内存空间是n*n*logn的(不需要管数的范围,范围再大也可以通过离散化缩小到n). 但是

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

Sequence II Time Limit: 9000/4500 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 849    Accepted Submission(s): 204 Problem Description Mr. Frog has an integer sequence of length n, which can be denoted as a1,a2,?

zoj 2112 Dynamic Rankings(主席树&amp;动态第k大)

Dynamic Rankings Time Limit: 10 Seconds      Memory Limit: 32768 KB The Company Dynamic Rankings has developed a new kind of computer that is no longer satisfied with the query like to simply find the k-th smallest number of the given N numbers. They

HDU 4417 (划分树+区间小于k统计)

题目链接:  http://acm.hdu.edu.cn/showproblem.php?pid=4417 题目大意:给定一个区间,以及一个k值,求该区间内小于等于k值的数的个数.注意区间是从0开始的. 解题思路: 首先这题线段树可以解.方法是维护一个区间最大值max,一个区间点个数s,如果k>max,则ans=s+Q(rson),否则ans=Q(lson). 然后也可以用求区间第K大的划分树来解决,在对原来求第K大的基础上改改就行,方法如下: Build方法同第K大. 对于Query: ①左区

zoj2112 主席树动态第k大 (主席树&amp;&amp;树状数组)

Dynamic Rankings Time Limit: 10 Seconds      Memory Limit: 32768 KB The Company Dynamic Rankings has developed a new kind of computer that is no longer satisfied with the query like to simply find the k-th smallest number of the given N numbers. They

HDU 3078 (LCA+树链第K大)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3078 题目大意:定点修改.查询树中任意一条树链上,第K大值. 解题思路: 先用离线Tarjan把每个Query树链的LCA求出来. LCA中对连接树Dfs的时候,令p[v]=u,记录v的前驱. LCA结束后,对于每个Query: 从u开始回溯到LCA,记录值.从v开始回溯到LCA,记录值. 再加上LCA这个点的值,形成一条完整树链.特判树链长度是否小于K. 对树链中的值,从大到小排序,取第K大即可

可持久化线段树 区间第k大

2018-04-04 http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1175 一个长度为N的整数序列,编号0 - N - 1.进行Q次查询,查询编号i至j的所有数中,第K大的数是多少. 例如: 1 7 6 3 1.i = 1, j = 3,k = 2,对应的数为7 6 3,第2大的数为6. Input 第1行:1个数N,表示序列的长度.(2 <= N <= 50000) 第2 - N + 1行:每行1个数,对应序列中

zoj2112 主席树动态第k大 ( 参考资料链接)

参考链接: http://blog.csdn.net/acm_cxlove/article/details/8565309 http://www.cnblogs.com/Rlemon/archive/2013/05/24/3096264.html http://seter.is-programmer.com/posts/31907.html http://blog.csdn.net/metalseed/article/details/8045038