AcWing
  • 首页
  • 课程
  • 题库
  • 更多
    • 竞赛
    • 题解
    • 分享
    • 问答
    • 应用
    • 校园
  • 关闭
    历史记录
    清除记录
    猜你想搜
    AcWing热点
  • App
  • 登录/注册

AcWing 1270. 离线区间最大值的另类求法    原题链接    简单

作者: 作者的头像   Link_Cut_Y ,  2023-12-01 13:38:56 ,  所有人可见 ,  阅读 52


1


将询问离线,按照右端点排序。然后从左往右扫,维护单调递增栈即可。

假设当前扫到 $i$,对于所有右端点在 $i$ 的询问,可以直接在单调栈里二分。

这样做的时间复杂度显然是 $O(n \log n)$。瓶颈在于二分。

#include <cstdio>
#include <algorithm>
#define rep(i, a, b) for (int i = (a); i <= (b); i ++ )

using namespace std;

void read() { return; }
template <typename T, typename ...T2>
void read(T &s, T2 &...oth) {
    s = 0; char ch = getchar(); bool f = 0;
    for (; ch < '0' or ch > '9'; ch = getchar()) if (ch == '-') f = 1;
    for (; ch >= '0' and ch <= '9'; ch = getchar()) s = (s << 1) + (s << 3) + (ch ^ 48);
    s = f ? -s : s; read(oth...); return;
}

const int N = 1000010;
int n, m, a[N], stk[N], ans[N], top;
struct Q {
    int l, r, id;
    bool operator < (const Q &t)const {
        return r < t.r;
    }
}q[N];
int solve(int x, int y) {
    int l = 1, r = top;
    while (l < r) {
        int mid = l + r >> 1;
        if (stk[mid] >= x) r = mid;
        else l = mid + 1;
    } return a[stk[l]];
}
int main() {
    read(n, m);
    rep(i, 1, n) read(a[i]);
    rep(i, 1, m) read(q[i].l, q[i].r), q[i].id = i;
    sort(q + 1, q + m + 1); int j = 1;
    rep(i, 1, n) {
        while (j <= m and q[j].r < i) j ++ ;
        while (top and a[stk[top]] <= a[i]) top -- ;
        stk[ ++ top] = i;
        while (j <= m and q[j].r == i)
            ans[q[j].id] = solve(q[j].l, q[j].r), j ++ ;
    }
    rep(i, 1, m) printf("%d\n", ans[i]);
    return 0;
}

然后发现可以将排序改成基数排序,复杂度瓶颈将变为二分栈的复杂度。

但是可以发现,可以利用并查集维护删点,因此时间复杂度变成 $O(n \alpha (n))$。

1 评论


用户头像
Link_Cut_Y   2023-12-01 13:39         踩      回复

可以做到和 ST 表类似的近线性复杂度。


App 内打开
你确定删除吗?
1024
x

© 2018-2025 AcWing 版权所有  |  京ICP备2021015969号-2
用户协议  |  隐私政策  |  常见问题  |  联系我们
AcWing
请输入登录信息
更多登录方式: 微信图标 qq图标 qq图标
请输入绑定的邮箱地址
请输入注册信息