首页 > 其他分享 >单调栈

单调栈

时间:2024-05-13 18:42:58浏览次数:24  
标签:mathbb www luogu oplus com problem 单调

单调栈:

可以线性预处理:序列前/后缀最大/小值的位置,或者是第 \(i\) 个数下一个更小/大数的位置。

B3666 求数列所有后缀最大值的位置 https://www.luogu.com.cn/problem/B3666

题意:

给一个初始为空的数列 \(a\) ,共 \(n\) 次操作,第 \(i(1 \leq i \leq n)\) 次操作会在 \(a\) 的末尾加入一个正整数 \(x\) 。

每次操作结束后,找到当前 \(a\) 的所有后缀最大值的下标(下标从 \(1\) 开始)。一个下标 \(i\) 是当前 \(a\) 的后缀最大值下标 \(iff\) :\(\forall j, i < j \leq |a|\) ,都有 \(a_i > a_j\) 。

每次操作结束输出当前数列所有后缀最大值的下标的按位异或和。

题解:

对于某个数列,显然任意元素 \(a_x\) 满足 \(\forall i > x, a_i < x\) ,则是后缀最大值。设所有 \(x\) 得到的序列为 \(\mathbb{P}\) 。

于是 \(\forall x < y \in \mathbb{P}\) ,有 \(a_x > a_y\) 。至少 \(\forall x \in \mathbb{P}\) 属于解集。

否则,至少存在 \(a_y \geq a_x \ s.t.\ y > x\) 。于是 \(\forall x \not \in \mathbb{P}\) 不属于解集。

于是 \(\forall x \in \mathbb{P}\) 为解集。

于是对于滑动的窗口,可以维护严格递减的单调栈,即动态维护序列 \(\mathbb{P}\) 。

现在答案貌似成为了:对每个滑动窗口的 \(x \in \mathbb{P}\) ,计算一遍按位异或和。但这显然是时间不允许的。

注意到按位异或的重要性质: \(x \oplus x = 0\) 。

考虑正难则反,区间的所有下标去除非法下标则是答案。要去除的即当前窗口下,单调栈中会被弹出的下标。维护历史弹出值的按位异或和即可。

窗口是维护前缀 \(pre(1, r)\) 的滑动,所以设 \(ans = \bigoplus_{i = 1}^{r} a_i\) 。然后 \(ans \oplus x \ s.t.\ x \in \mathbb{P}, a_x \leq a_r\) 。

前缀异或可以在线处理 \(ans \oplus r\) 。也存在

\[ans = \begin{cases} r, r \equiv r (\bmod 4) \\ 1, r \equiv 1 (\bmod 4) \\ r + 1, r \equiv 2 (\bmod 4) \\ 0, r \equiv 3 (\bmod 4) \\ \end{cases} \]

考虑证明,设 \(a = ???00, b = ???01, c = ???10, d = ???11\) 。

\[\begin{cases} 0 \oplus a = a \\ 0 \oplus a \oplus b = 1 \\ 0 \oplus a \oplus b \oplus c = c + 1 \\ 0 \oplus a \oplus b \oplus c \oplus = 0 \\ \end{cases} \]

int n; std::cin >> n;
std::vector<u64> a(n + 1);
std::stack<u64> stk;
auto calc = [&] (int X) -> u64 {
    if (X % 4 == 0) return X;
    if (X % 4 == 1) return 1;
    if (X % 4 == 2) return X + 1;
    if (X % 4 == 3) return 0;
    return -1;
};
u64 remove = 0;
for (int i = 1; i <= n; i++) {
    std::cin >> a[i];
    u64 res = 0;
    while (!stk.empty() && a[i] >= a[stk.top()]) {
        remove ^= stk.top();
        stk.pop();
    }
    stk.push(i);
    std::cout << (remove ^ calc(i)) << "\n";
}

P2866 [USACO06NOV] Bad Hair Day S https://www.luogu.com.cn/problem/P2866

题意:

P1901 发射站 https://www.luogu.com.cn/problem/P1901

P4147 玉蟾宫 https://www.luogu.com.cn/problem/P4147

P9461 「EZEC-14」众数 II https://www.luogu.com.cn/problem/P9461

P9607 [CERC2019] Be Geeks! https://www.luogu.com.cn/problem/P9607

P10169 [DTCPC 2024] mex,min,max https://www.luogu.com.cn/problem/P10169

标签:mathbb,www,luogu,oplus,com,problem,单调
From: https://www.cnblogs.com/zsxuan/p/18189092

相关文章

  • BZOJ5424 烧桥计划(单调队列优化dp)
    传送门(vjudge)解题思路注意到\(a_i\)的范围很小,是1000~2000之间,于是我们可以直观感受到k一定不会特别大,推一下可以得出k最多大概在四五百左右,于是可以直接考虑dp[i][j]为前i个数里面选了j个分割点,且第i个数是分割点的最小代价。转移要分两种情况讨论:sum[pre+1~i......
  • 单调队列优化DP
    单调队列优化dp单调队列可以求某固定区间的最值,所以dp中需要求某固定区间的最值则可以考虑使用单调队列优化单调队列-滑动窗口https://www.luogu.com.cn/problem/P1886/**@Author:Danc1ng*@Date:2024-04-2416:06:34*@FilePath:P1886滑动窗口[模......
  • [dp 小计] 决策单调性优化
    我要急眼了,看了一个破博客写错的浪费我两个小时Task1先讲讲最简单的类型。通常,都是一类类似\(f_i=\min_{j=1}^if_j+w(i,j)\)决策单调,字面意思,就是每次取的点都是右移的。先声明一下,四边形不等式是决策单调性的充分不必要条件。只证明充分条件。令\(w\)满足\(w(a,c)+w......
  • 【二分+容斥】【ST表/单调栈】【划分型DP】
    二分+容斥题目链接https://leetcode.cn/problems/kth-smallest-amount-with-single-denomination-combination/description/题目大意题目思路假设有一个x元硬币思考只有一种面额为3的硬币时,3可以组成不超过x的面额的数量有x/3种!思考有两种面额【3,6】,可以组成不......
  • 【Go】单调栈
    寿司店周年庆,正在举办优惠活动只回馈新老客户寿司转盘上总共有n盘寿司,prices是第i盘寿司的价格,如果客户选择了第i密寿司,寿司店免费赠送客户距离第i盘寿司最近的下一盘寿可j,前提是pricesm<pricesū,如果没有满足条件的ì,则不赠送寿司。每个价格的寿司都可无限供应。输入描述输......
  • ACwing830 单调栈
    这道题是P8600[蓝桥杯2013省B]连号区间数的前置知识#include<iostream>#include<stdio.h>#include<algorithm>#include<string>#include<cmath>#defineR(x)x=read()#defineFor(i,j,n)for(inti=j;i<=n;++i)usingnamespa......
  • 二分+单调队列优化 2
    7-7列车调度(天梯赛选拔赛)https://pintia.cn/problem-sets/1768624240956489728/exam/problems/1768624240990044166?type=7&page=0火车站的列车调度铁轨的结构如下图所示。两端分别是一条入口(Entrance)轨道和一条出口(Exit)轨道,它们之间有N条平行的轨道。每趟列车从入口可以......
  • 二分+单调队列思想
    [AHOI2018初中组]分组(洛谷P4447)题目描述小可可的学校信息组总共有\(n\)个队员,每个人都有一个实力值\(a_i\)。现在,一年一度的编程大赛就要到了,小可可的学校获得了若干个参赛名额,教练决定把学校信息组的\(n\)个队员分成若干个小组去参加这场比赛。但是每个队员都不会愿意与......
  • 单调栈 and 单调队列学习笔记
    单调栈and单调队列学习笔记本文均以维护单调递增的栈/队列举例。本篇代码合集以后在写动态规划单调队列/单调栈优化的时候,这两个东西会合并。单调栈本质上就是模拟。假设要维护一个单调递增的栈,那么对于一个元素进来了,在栈顶的所有比他小的数我全部都要踢出去,不然就不满足......
  • 单调栈
    依据单调栈具有贼有趣的实现方式:在查找的同时,删除多余的,插入新的那么删除插入的过程和依据呢?我是nums[i],以找出左边第一个比我小的元素为例:栈里的元素是非降序的,而且都在我左边凡是栈里比我大的数(记为big),对找出左边第一个比我小的数来说,无效,可删对我右边的数来说,big也是对......