高效解决子数组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
相关产品推荐
相关产品推荐

