题解 P8251 [NOI Online 2022 提高组] 丹钓战
先考虑一个弱化问题:多次询问将一个区间 \([l,r]\) 内的所有数加入单调栈之后(下文称这样是对一个区间进行操作。),栈内是否只剩下一个元素。
首先当 \(l=r\) 的时候一定只剩下一个数。
依题意所说,我们可以把 \([1,n]\) 内的所有元素加入栈内模拟一遍,预处理出元素 \(i\) 会被 \(p_i\) 弹出栈,这一步可以 \(\mathcal{O}(n)\) 做到。
我们可以发现,如果一个区间 \([l,r]\) 满足它最后只剩下一个元素,那么必然满足 \(\forall i\in[l,r-1],p_i\leq r\)。
于是我们只需要查询一下 \(\max_{i=l}^{r-1} p_i\) 即可解决这个弱化的问题,利用 st 表就可以做到 \(\mathcal{O}(n\log_2 n)-\mathcal{O}(1)\)。
有一个结论,如果 \([l,r](l<r)\) 这个区间操作之后只剩下一个元素,那么 \([l+1,r]\) 这个区间操作之后也只剩下一个元素。
感性理解一下,这两个区间只差了 \((a_l,b_l)\) 这一个元素,而它没有弹出任何一个其他元素,形象的来说它成了区间的"累赘",它只能等待别的元素把它弹掉。所以把它删掉也没有影响。
依次启发,我们可以对每个 \(i\) 预处理一个 \(least_i\),表示 \([least_i,i]\) 这个区间操作后只剩下一个元素,但是 \([least_i-1,i]\) 这个区间操作后剩下的元素个数 \(>1\)(\(\forall i,least_i\geq 1\)),依照上面的结论,我们可以对于每个 \(i\) 二分出 \(least_i\),这部分的复杂度是 \(\mathcal{O}(n\log_2 n)\)。
考虑询问,我们发现询问就是问 \([l,l],[l,l+1],\dots,[r-1,r],[r,r]\) 这些区间有多少个操作之后只剩下一个元素,也就是询问区间 \([l,r]\) 中有多少个 \(least_i\leq l\)。
这就是一个经典问题了:将询问差分,变为询问 \([1,l-1]\) 中有多少个 \(least_i\leq l\)(显然 \(least_i\leq i\),所以这部分答案是 \(l-1\)),询问 \([1,r]\) 中有多少个 \(least_i\leq l\)。对于后者,离线之后树状数组查询即可。
最终时间复杂度 \(\mathcal{O}(n\log_2 n)\)。

题解 P8251 [NOI Online 2022 提高组] 丹钓战
浙公网安备 33010602011771号