标签: 可持久化线段树
题目描述
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
", 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
", query(0,1,n,T[l-1],T[r]));
}
}
return 0;
}