给你一个数组,以及 k 个大小关系,然后要你找到一个最长的子序列,使得它相邻的两个数依次满足 k 个大小关系(跑完 k 个就回到一开始继续)
MOT-Monotonicity 2
题目大意
给你一个数组,以及 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__
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现