P8251 [NOI Online 2022 提高组] 丹钓战

题意:

有 n 个二元组 (ai,bi),编号为 1 到 n。

有一个初始为空的栈 S,向其中加入元素 (ai,bi) 时,先不断弹出栈顶元素直至栈空或栈顶元素 (aj,bj) 满足 ai≠aj 且 bi<bj,然后再将其加入栈中。

如果一个二元组入栈后栈内只有这一个元素,则称该二元组是“成功的”。

有 q 个询问 li,ri,表示若将编号在 li,ri 中的二元组按编号从小到大依次入栈,会有多少个二元组是“成功的”。

询问之间相互独立。

思路:

首先找找这个单调栈的性质。。。好复杂啊找不出!

正确做法是先模拟一遍题中的单调栈

离线询问,树状数组求区间中小于等于 ki 的数量,还有一种写法 yangege的题解

const signed N = 5e5 + 3;
int n, q, ans[N]; PII p[N];
vector<PII> qry[N]; //qry[l]={<r,id>,...}
int stk[N], top;

struct node {
    int val, pos;
} a[N];
bool cmp(node x, node y) {
    if(x.val != y.val) return x.val < y.val;
    return x.pos > y.pos; //相等的优先处理右边的
}

signed main() {
    iofast;
    cin >> n >> q;
    for(int i = 1; i <= n; i++) cin >> p[i].fi;
    for(int i = 1; i <= n; i++) cin >> p[i].se;

    for(int i = 1; i <= n; i++) { //模拟单调栈
        while(top && (p[stk[top]].fi == p[i].fi
            || p[stk[top]].se <= p[i].se)) top--;
        a[i] = {stk[top], i};
        stk[++top] = i;
    }

    for(int i = 1; i <= q; i++) {
        int l, r; cin >> l >> r;
        qry[l].pb({r,i});
    }

    sort(a + 1, a + 1 + n, cmp);
    for(int i = 1; i <= n; i++) {
        int l = a[i].pos;
        add(l, 1);
        for(auto &[r,id] : qry[l])
            ans[id] = ask(r) - ask(l-1);
    }

    for(int i = 1; i <= q; i++) cout << ans[i] << endl;
}

posted @   Bellala  阅读(57)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示