CF1693D

题面

定义一个序列 a 是好的,仅当可以通过删除 a 的一个单调递减子序列(可以为空)使得 a 单调递增。
给定一个 1n 的排列 p,你需要求出 p 有多少子段是好的。

数据范围: n2×105

题解

方法多样。

  • 自己的方法

考虑cdq分治,对于 mid 处理 l<midr 的答案。

现在考虑处理大于等于 mid 的这一边。

我们可以对 mid 枚举一下是做上升的,还是下降的。

以上升为例,可以证明,在 mid 右边且作为下降的点一定是 ajaj+1 其中 j 是最小的 jmidaj>aj+1 ,那么我们就再枚举一下是哪一个,然后直接求出对应的 r 最远是多少。

这样把每种情况都求出来(同样对于 <mid 的部分),就会得到 4×4l,r 对,然后去一下重就行了。

但是我没写qwq(所以也没法保证正确性),因为实在是太复杂了,还是考虑一下简单的做法。

  • 官方题解做法

考虑如何判断一个序列有解,有一个显然的 dp:

fi 为从起点到 ii 是作为上升的 ,此时最后一个下降的值最大是多少,gi 反过来。

然后答案就是枚举起点然后计算一次到哪个位置时不合法了。

但这是 O(n2) 的,但题解告诉你,如果你从后往前枚举起点然后去更新,可以做到 O(n) 的复杂度!

为什么?

因为对于 fi 来说,设 j 为小于 i 中第一个满足 aj1>aj 的,那么 fi 的值只可能是 inf,aj1,aj,inf 这四个值。

而且修改是单调的,所以修改此时是 O(1) 的,然后我们就可以暴力往后修改而通过了。

  • luogu题解区神奇做法

核心:设 ansi 为最大的 ansi 使得 [i,ansi] 为合法的,那么 ansi 单调。

那么如果 ansl=ansr 那么对于 i[l,r],ansi=ansl

所以可以考虑分治,对于区间 [l,r],我们先求出 anslansr,若 ansl=ansr,那么直接更新,否则递归处理 [l+1,mid][mid+1,r1]

因为我们求一个 ansl 的复杂度是 O(ansl) 的,所以不容易被卡,甚至复杂度就是正确的。。。

反正是个新颖的乱搞做法吧。

启发

  • 分析一下题目的性质就可以让一些看起来很假的做法优化成正确的做法

本文作者:qwq_123

本文链接:https://www.cnblogs.com/qwq-123/p/16403542.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   qwq_123  阅读(62)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起