You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

高效解决子数组H指数区间查询问题的优化方案求助

高效解决子数组H指数区间查询问题的优化方案求助

我现在卡在一个子数组H指数的区间查询问题上,想请教下有没有更高效的解法!先跟大家说下问题背景:

H指数的定义是最大的整数h,表示某作者至少有h篇论文每篇被引用至少h次。现在给了N篇论文,第i篇的引用数是p[i],还有Q个查询,每个查询给一个区间[l, r],要求只考虑这个区间内的论文时,对应的H指数是多少。N、Q和所有p[i]的范围都是1到2*10^5。

举个实际例子:

输入对应的p数组是[5,7,4,1],查询区间[2,3]时,这个区间里的两篇论文引用数是7和4,都≥2,且刚好有2篇,所以H指数是2;查询[3,4]时,满足≥1的论文有2篇,但尝试h=2时只有1篇(引用4的论文)满足≥2,所以最大h是1,输出为1。

我最开始的思路是对每个查询的子数组做二分查找:对每个查询,二分h的可能值,然后遍历区间统计有多少篇论文的引用数≥h,这样每个查询的时间复杂度是O((r-l+1)logN),整体下来是O(Q*NlogN)。我写了对应的代码,结果是对的,但超时了——哪怕我用了scanf或者cin.tie(0);ios::sync_with_stdio(0);来加速输入输出,还是过不了3秒的时间限制。

下面是我写的超时代码:

#include <iostream>
int p[200005];
int main() {
    using namespace std;
    int n;
    cin >> n;
    int q;
    cin >> q;
    for (int i = 0; i < n; i++) {
        cin >> p[i + 1];
    }
    for (int i = 0; i < q; i++) {
        int l;
        cin >> l;
        int r;
        cin >> r;
        int lo = 1, hi = n;
        while (lo <= hi) {
            int mid = (lo + hi) / 2;
            int cnt = 0;
            for (int j = l; j <= r; j++) {
                if (p[j] >= mid) {
                    cnt++;
                }
            }
            if (cnt >= mid) {
                lo = mid + 1;
            } else {
                hi = mid - 1;
            }
        }
        cout << hi << '\n';
    }
}

我也考虑过用线段树来优化,但不知道怎么合并线段树的节点才能避免线性时间的操作——如果合并还是O(N)的话,那跟暴力解法也没区别了。现在的核心问题就是时间复杂度,每个查询的时间必须远低于O(N)才行。有没有大佬能给我指条明路,怎么在时间限制内解决这个问题呀?

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.07 07:20:28