Just h-index 2018湘潭邀请赛

标签: 可持久化线段树


题目描述

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 \(a_1 , a_2 ,..., a_n\) 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 \(a_{li}, a_{li+1},..., a_{ri}\) .

输入

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 \(a_1 , a_2 ,..., a_n\) .
The i-th of last q lines contains two integers \(l_i\) and \(r_i\) .

输出

For each question, print an integer which denotes the answer.
\(1 ≤ n, q ≤ 10^5\)
\(1 ≤ a_i ≤ n\)
\(1 \leq l_i \leq r_i \leq n\)
• The sum of n does not exceed 250,000.
• The sum of q does not exceed 250,000.

样例输入

5 3
1 5 3 2 1
1 3
2 4
1 5
5 1
1 2 3 4 5
1 5

样例输出

2
2
2
3

分析

  对权值通过维护一个可持久化线段树.
  将数组的区间\([l,r]\)抽象为第l到第r次修改产生的影响.
  每次查询的时候,我们应当找到满足\(x \in [l,r]\)\(\sum_{i=x}^{r}a_i>=x\)的最大的\(x\)

代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn=100050;
int n,q,a[maxn];
int sz,sum[maxn*20],lson[maxn*20],rson[maxn*20];
int update(int x,int l,int r,int id){
    int root=++sz;
    if(l==x&&r==x){
        sum[root]=sum[id]+1;
        lson[root]=rson[root]=0;
        return root;
    }
    int mid=(l+r)>>1;
    if(x<=mid){
        lson[root]=update(x,l,mid,lson[id]);
        rson[root]=rson[id];
    }
    else{
        lson[root]=lson[id];
        rson[root]=update(x,mid+1,r,rson[id]);
    }
    sum[root]=sum[lson[root]]+sum[rson[root]];
    return root;
}
int query(int suf,int l,int r,int r1,int r2){
//    printf("%d %d %d\n", k,l,r);
    if(l==r){
        return l;
    }
    int s=sum[rson[r2]]-sum[rson[r1]];
    int mid=(l+r)>>1;
    if(s+suf>=mid+1) return query(suf,mid+1,r,rson[r1],rson[r2]);
    else return query(s+suf,l,mid,lson[r1],lson[r2]);
}
int T[maxn];
int main(int argc, char const *argv[])
{
    while(~scanf("%d%d", &n,&q)){
        T[0]=0;
        sz=0;
        for (int i = 1; i <= n; ++i)
        {
            scanf("%d", &a[i]);
            T[i]=update(a[i],1,n,T[i-1]);
        }
        while(q--){
            int l,r;
            scanf("%d%d", &l,&r);
            printf("%d\n", query(0,1,n,T[l-1],T[r]));
        }
    }
    return 0;
}
posted @ 2018-05-19 00:20  sciorz  阅读(655)  评论(2编辑  收藏  举报