【luogu P3506】MOT-Monotonicity 2(线段树)

MOT-Monotonicity 2

题目链接:luogu P3506

题目大意

给你一个数组,以及 k 个大小关系,然后要你找到一个最长的子序列,使得它相邻的两个数依次满足 k 个大小关系(跑完 k 个就回到一开始继续)

思路

考虑 DP,但是普通的 DP 并不可以。
考虑用线段树优化。

其实就分成三个 DP,代表下一个符号是哪个,最后一个数是啥的最大长度。
然后至于方案你就记录一下到时跑回去即可。

代码

#include<cstdio> #include<iostream> #include<algorithm> using namespace std; int n, k, a[500001], tmp[500001]; int pl[500001][3]; char c, s[500001]; struct XD_tree { int a[500001 << 2], p[500001 << 2]; void up(int now) { if (a[now << 1] > a[now << 1 | 1]) a[now] = a[now << 1], p[now] = p[now << 1]; else a[now] = a[now << 1 | 1], p[now] = p[now << 1 | 1]; } void insert(int now, int l, int r, int pl, int va, int vp) { if (l == r) { if (va > a[now]) { a[now] = va; p[now] = vp; } return ; } int mid = (l + r) >> 1; if (pl <= mid) insert(now << 1, l, mid, pl, va, vp); else insert(now << 1 | 1, mid + 1, r, pl, va, vp); up(now); } pair <int, int> query(int now, int l, int r, int L, int R) { if (L > R) return make_pair(0, 0); if (L <= l && r <= R) return make_pair(a[now], p[now]); int mid = (l + r) >> 1, re = 0; if (L > mid) return query(now << 1 | 1, mid + 1, r, L, R); if (mid >= R) return query(now << 1, l, mid, L, R); pair <int, int> x = query(now << 1, l, mid, L, R); pair <int, int> y = query(now << 1 | 1, mid + 1, r, L, R); if (x.first > y.first) return x; else return y; } }T[3]; void csh() {//离散化 for (int i = 1; i <= n; i++) tmp[++tmp[0]] = a[i]; sort(tmp + 1, tmp + tmp[0] + 1); tmp[0] = unique(tmp + 1, tmp + tmp[0] + 1) - tmp - 1; for (int i = 1; i <= n; i++) a[i] = lower_bound(tmp + 1, tmp + tmp[0] + 1, a[i]) - tmp; } int get_op(int i) { if (s[i] == '<') return 0; if (s[i] == '=') return 1; return 2; } void dfs(int now, int num) {//按着记录找回去 if (!num) return ; dfs(pl[now][get_op((num - 2 + k) % k)], num - 1); printf("%d ", tmp[a[now]]);//因为你离散化了,所以你要输出的是你找到的位置对于的数在离散化前的结果 } int main() { scanf("%d %d", &n, &k); for (int i = 1; i <= n; i++) scanf("%d", &a[i]); csh(); for (int i = 0; i < k; i++) { c = getchar(); while (c != '=' && c != '<' && c != '>') c = getchar(); s[i] = c; } for (int i = 1; i <= n; i++) { pair <int, int> x; x = T[0].query(1, 1, n, 1, a[i] - 1); pl[i][0] = x.second; T[get_op(x.first % k)].insert(1, 1, n, a[i], x.first + 1, i); x = T[1].query(1, 1, n, a[i], a[i]); pl[i][1] = x.second; T[get_op(x.first % k)].insert(1, 1, n, a[i], x.first + 1, i); x = T[2].query(1, 1, n, a[i] + 1, n); pl[i][2] = x.second; T[get_op(x.first % k)].insert(1, 1, n, a[i], x.first + 1, i); } pair <int, int> x = max(T[0].query(1, 1, n, 1, n), max(T[1].query(1, 1, n, 1, n), T[2].query(1, 1, n, 1, n))); printf("%d\n", x.first); dfs(x.second, x.first); return 0; }

__EOF__

本文作者あおいSakura
本文链接https://www.cnblogs.com/Sakura-TJH/p/luogu_P3506.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   あおいSakura  阅读(25)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示