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;
}
标签:
树状数组
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话