【luogu CF1693D】Decinc Dividing(DP)

Decinc Dividing

题目链接:luogu CF1693D

题目大意

给你一个排列,问你有多少个区间满足可以删掉一个单调递减子序列(可以是空的)得到一个单调递增数组。

思路

其实题目就是问你有多少个区间能划分成一个上升子序列和下降子序列。
首先我们考虑枚举左端点,往右扩展的时候 DP,那就是 n2 的。
(因为有一个比较显然的性质是如果 [l,r] 不行 [l,r+1] 更加不行,所以固定左端点只有,合法的区间的右端点是一段前缀)

怎么 O(n) DP呢,一个事情就是你要用一维记录下两个序列的最后一个。
那必然有其中一个是你当前的位置,所以你只需要记录另一个位置即可。
那我们设:
fi,0i 所在的递增,递减最后一个数最大值
fi,1i 所在的递减,递增最后一个数最小值
(这个最大和最小是尽可能给后面留空间)

(其中 fi,0 初始值为 inffi,1 初始值为 inf,也代表无解值)
(然后初始化是 fi,0=inf,fi,1=inf

然后考虑转移,你就直接看新的数是放在哪个序列,能不能放。
考虑优化,我们试着左端点从右往左,每次新加入一个点会怎样呢?
好像不会咋样。

但是如果你 fi,0,fi,1 DP 出来的结果跟之前一样,那你没必要继续下去,直接去上一轮的结果就行。
因为这个 DP 只会从 fi1,0/1 来更新 fi,0/1

那这个记忆化好像也没啥用。
我们试着看看每个位置的取值。
首先 inf,inf 都有,那我们再看会不会有别的值。
fi,0 为例子,fi,1 同理。

我们找到 i 前面最大的 j 使得 aj>aj+1,那 aj,aj+1 不能都在递增的序列中,那就要放到递减的,又因为是最大的 j,所以要么是 aj 做了最后的值,要么是 aj+1
那如果没有这个 j,那就是初始化 1 位置的 inf
如果无解,就是无解的 inf

fi,0 就只有四种取值最多,fi,1 也一样。
一个显然的事情是随着左端点的左移,这个值如果改变也只会单向的变化(变得更加容易无解)。
所以其实一个位置的值至多边 7 次,八种情况。

所以我们可以直接暴力从这个位置开始 DP,如果 DP 到的值跟之前的一样就直接用之前的位置作为答案进行贡献。

代码

#include<cstdio> #include<iostream> #define ll long long #define INF (0x3f3f3f3f3f3f3f3f) using namespace std; const int N = 2e5 + 100; int n, a[N], f[N][2], lst; ll ans; //0:i递增,递减最后一个数最大值 //1:i递减,递增最后一个数最小值 int slove(int i) { f[i][0] = INF; f[i][1] = -INF; int tmp = INF; for (int j = i + 1; j <= n; j++) { int v0 = -INF, v1 = INF; if (f[j - 1][0] != -tmp) { if (a[j] > a[j - 1]) v0 = max(v0, f[j - 1][0]); if (a[j] < f[j - 1][0]) v1 = min(v1, a[j - 1]); } if (f[j - 1][1] != tmp) { if (a[j] < a[j - 1]) v1 = min(v1, f[j - 1][1]); if (a[j] > f[j - 1][1]) v0 = max(v0, a[j - 1]); } if (v0 == f[j][0] && v1 == f[j][1]) break; f[j][0] = v0; f[j][1] = v1; if (f[j][0] == -tmp && f[j][1] == tmp) { lst = j - 1; return j - i; } } return lst - i + 1; } int main() { scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", &a[i]); lst = n; for (int i = n; i >= 1; i--) ans += slove(i); printf("%lld", ans); return 0; }

__EOF__

本文作者あおいSakura
本文链接https://www.cnblogs.com/Sakura-TJH/p/luogu_CF1693D.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   あおいSakura  阅读(46)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示